From 0ec823ce5b72bcf3be3923f2f23e5386feb0107b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Dec 2008 12:30:14 -0800 Subject: [PATCH 001/462] Add build infrastructure for glamor. --- Makefile.am | 2 ++ configure.ac | 1 + glamor/Makefile.am | 18 +++++++++++ glamor/glamor.c | 37 +++++++++++++++++++++ glamor/glamor.h | 26 +++++++++++++++ hw/kdrive/ephyr/Makefile.am | 5 ++- hw/kdrive/ephyr/ephyr.h | 6 ++++ hw/kdrive/ephyr/ephyr_glamor.c | 59 ++++++++++++++++++++++++++++++++++ hw/kdrive/ephyr/ephyrinit.c | 9 ++++++ 9 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 glamor/Makefile.am create mode 100644 glamor/glamor.c create mode 100644 glamor/glamor.h create mode 100644 hw/kdrive/ephyr/ephyr_glamor.c diff --git a/Makefile.am b/Makefile.am index cea140bea..0c701633d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,6 +38,7 @@ SUBDIRS = \ $(COMPOSITE_DIR) \ $(GLX_DIR) \ exa \ + glamor \ config \ hw \ test @@ -88,6 +89,7 @@ DIST_SUBDIRS = \ composite \ glx \ exa \ + glamor \ config \ hw \ test diff --git a/configure.ac b/configure.ac index b0d26435a..85d5b706f 100644 --- a/configure.ac +++ b/configure.ac @@ -2133,6 +2133,7 @@ Xext/Makefile Xi/Makefile xfixes/Makefile exa/Makefile +glamor/Makefile hw/Makefile hw/xfree86/Makefile hw/xfree86/common/Makefile diff --git a/glamor/Makefile.am b/glamor/Makefile.am new file mode 100644 index 000000000..8f4c60758 --- /dev/null +++ b/glamor/Makefile.am @@ -0,0 +1,18 @@ +noinst_LTLIBRARIES = libglamor.la + +# Override these since glamor doesn't need them and the needed files aren't +# built (in hw/xfree86/os-support/solaris) until after glamor is built +SOLARIS_ASM_CFLAGS="" + +if XORG +sdk_HEADERS = glamor.h +endif + +INCLUDES = \ + $(XORG_INCS) + +AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) + +libglamor_la_SOURCES = \ + glamor.c \ + glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c new file mode 100644 index 000000000..718cce3cf --- /dev/null +++ b/glamor/glamor.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/** @file + * This file covers the initialization and teardown of glamor, and has various + * functions not responsible for performing rendering. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include diff --git a/glamor/glamor.h b/glamor/glamor.h new file mode 100644 index 000000000..7aa4a73dc --- /dev/null +++ b/glamor/glamor.h @@ -0,0 +1,26 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 9d9b64ee5..79e950bb5 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -7,7 +7,8 @@ INCLUDES = \ @XEPHYR_CFLAGS@ \ @DRIPROTO_CFLAGS@ \ -I$(top_srcdir) \ - -I$(top_srcdir)/exa + -I$(top_srcdir)/exa \ + -I$(top_srcdir)/glamor if XV LIBXEPHYR_HOSTXV=libxephyr-hostxv.la @@ -47,6 +48,7 @@ XEPHYR_SRCS = \ ephyr.h \ ephyrlog.h \ ephyr_draw.c \ + ephyr_glamor.c \ os.c libxephyr_hostx_la_SOURCES = $(HOSTX_SRCS) @@ -70,6 +72,7 @@ Xephyr_LDADD = \ $(LIBXEPHYR_HOSTXV) \ $(LIBXEPHYR_HOSTDRI) \ $(top_builddir)/exa/libexa.la \ + $(top_builddir)/glamor/libglamor.la \ @KDRIVE_LIBS@ \ @XEPHYR_LIBS@ diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index 23848004c..cd1521209 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -196,6 +196,12 @@ ephyrDrawDisable(ScreenPtr pScreen); void ephyrDrawFini(ScreenPtr pScreen); +/* ephyr_glamor.c */ +Bool ephyr_glamor_init(ScreenPtr pScreen); +void ephyr_glamor_enable(ScreenPtr pScreen); +void ephyr_glamor_disable(ScreenPtr pScreen); +void ephyr_glamor_fini(ScreenPtr pScreen); + /*ephyvideo.c*/ Bool ephyrInitVideo(ScreenPtr pScreen) ; diff --git a/hw/kdrive/ephyr/ephyr_glamor.c b/hw/kdrive/ephyr/ephyr_glamor.c new file mode 100644 index 000000000..f4fb3df05 --- /dev/null +++ b/hw/kdrive/ephyr/ephyr_glamor.c @@ -0,0 +1,59 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ephyr.h" +/*#include "glamor.h"*/ + +/** + * This function initializes EXA to use the fake acceleration implementation + * which just falls through to software. The purpose is to have a reliable, + * correct driver with which to test changes to the EXA core. + */ +Bool +ephyr_glamor_init(ScreenPtr pScreen) +{ + return TRUE; +} + +void +ephyr_glamor_enable(ScreenPtr pScreen) +{ +} + +void +ephyr_glamor_disable(ScreenPtr pScreen) +{ +} + +void +ephyr_glamor_fini(ScreenPtr pScreen) +{ +} diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index b674bb8d0..4b291813a 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -117,6 +117,7 @@ ddxUseMsg (void) ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); ErrorF("-grayscale Simulate 8bit grayscale\n"); + ErrorF("-glamor Enable 2D acceleration using glamor\n"); ErrorF("-fakexa Simulate acceleration using software rendering\n"); ErrorF("-verbosity Set log verbosity level\n"); #ifdef GLXEXT @@ -220,6 +221,14 @@ ddxProcessArgument (int argc, char **argv, int i) EphyrWantGrayScale = 1; return 1; } + else if (!strcmp (argv[i], "-glamor")) + { + ephyrFuncs.initAccel = ephyr_glamor_init; + ephyrFuncs.enableAccel = ephyr_glamor_enable; + ephyrFuncs.disableAccel = ephyr_glamor_disable; + ephyrFuncs.finiAccel = ephyr_glamor_fini; + return 1; + } else if (!strcmp (argv[i], "-fakexa")) { ephyrFuncs.initAccel = ephyrDrawInit; From da6e0ffad2173d65f27feff36291f94e6aa06f88 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Dec 2008 14:00:05 -0800 Subject: [PATCH 002/462] More ephyr/glamor glue. --- glamor/glamor.c | 12 +++++++++++- glamor/glamor.h | 14 ++++++++++++++ hw/kdrive/ephyr/Makefile.am | 3 ++- hw/kdrive/ephyr/ephyr_glamor.c | 19 +++++++++++++------ hw/kdrive/ephyr/hostx.h | 3 +++ 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 718cce3cf..49771ce9d 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -25,7 +25,7 @@ * */ -/** @file +/** @file glamor.c * This file covers the initialization and teardown of glamor, and has various * functions not responsible for performing rendering. */ @@ -35,3 +35,13 @@ #endif #include + +#include "glamor.h" + +/** Set up glamor for an already-configured GL context. */ +Bool +glamor_init(ScreenPtr screen) +{ + return Success; +} + diff --git a/glamor/glamor.h b/glamor/glamor.h index 7aa4a73dc..e6f303845 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -24,3 +24,17 @@ * Eric Anholt * */ + +#ifndef GLAMOR_H +#define GLAMOR_H + +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "picturestr.h" +#include "fb.h" + +#endif /* GLAMOR_H */ + +Bool glamor_init(ScreenPtr screen); diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 79e950bb5..027db1364 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -24,7 +24,8 @@ bin_PROGRAMS = Xephyr HOSTX_SRCS = \ hostx.c \ - hostx.h + hostx.h \ + ephyr_host_glamor.c HOSTVIDEO_SRCS = \ ephyrvideo.c \ diff --git a/hw/kdrive/ephyr/ephyr_glamor.c b/hw/kdrive/ephyr/ephyr_glamor.c index f4fb3df05..2e2d946a9 100644 --- a/hw/kdrive/ephyr/ephyr_glamor.c +++ b/hw/kdrive/ephyr/ephyr_glamor.c @@ -1,5 +1,5 @@ /* - * Copyright © 2006 Intel Corporation + * Copyright © 2008 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,7 +30,7 @@ #endif #include "ephyr.h" -/*#include "glamor.h"*/ +#include "glamor.h" /** * This function initializes EXA to use the fake acceleration implementation @@ -38,22 +38,29 @@ * correct driver with which to test changes to the EXA core. */ Bool -ephyr_glamor_init(ScreenPtr pScreen) +ephyr_glamor_init(ScreenPtr screen) { + KdScreenPriv(screen); + KdScreenInfo *kd_screen = pScreenPriv->screen; + + ephyr_glamor_host_create_context(kd_screen); + + glamor_init(screen); + return TRUE; } void -ephyr_glamor_enable(ScreenPtr pScreen) +ephyr_glamor_enable(ScreenPtr screen) { } void -ephyr_glamor_disable(ScreenPtr pScreen) +ephyr_glamor_disable(ScreenPtr screen) { } void -ephyr_glamor_fini(ScreenPtr pScreen) +ephyr_glamor_fini(ScreenPtr screen) { } diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 42578576a..d5cb0faa6 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -261,4 +261,7 @@ int hostx_has_dri (void) ; int hostx_has_glx (void) ; #endif /* XF86DRI */ +/* ephyr_glamor_host.c */ +void ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen); + #endif /*_XLIBS_STUFF_H_*/ From 8885b3b1ffb45ae16484151ce533683af526f509 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Dec 2008 15:08:21 -0800 Subject: [PATCH 003/462] Add exa/glamor to _DEPENDENCIES so the bin gets rebuilt with the libs. --- hw/kdrive/ephyr/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 027db1364..349e86dca 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -80,6 +80,8 @@ Xephyr_LDADD = \ Xephyr_DEPENDENCIES = \ libxephyr.la \ libxephyr-hostx.la \ + $(top_builddir)/exa/libexa.la \ + $(top_builddir)/glamor/libglamor.la \ $(LIBXEPHYR_HOSTXV) \ $(LIBXEPHYR_HOSTDRI) \ @KDRIVE_LOCAL_LIBS@ From 41e3e580de95fca3095d015ec8febe1a5f47cca3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 10:49:41 -0700 Subject: [PATCH 004/462] glamor: Use -lgl for Xephyr if GLX is unset. I'm experimenting with that because of conflicts with GL dispatch tables. --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 85d5b706f..10069be66 100644 --- a/configure.ac +++ b/configure.ac @@ -1998,6 +1998,10 @@ if test "$KDRIVE" = yes; then if test "x$DRI" = xyes && test "x$GLX" = xyes; then XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm" fi + # The glamor stuff requires libGL, but that conflicts with GLX currently. + if test "x$GLX" = xno; then + XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS gl" + fi PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"]) if test "x$XEPHYR" = xauto; then From 4d52ae7f2dca78d493e11375d764c978db5567ed Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Dec 2008 15:14:31 -0800 Subject: [PATCH 005/462] glamor: Start trying to hook up the rendering bits --- glamor/Makefile.am | 1 + glamor/glamor.c | 66 ++++++++- glamor/glamor.h | 1 + glamor/glamor_core.c | 216 ++++++++++++++++++++++++++++ glamor/glamor_priv.h | 53 +++++++ hw/kdrive/ephyr/ephyr_glamor.c | 1 + hw/kdrive/ephyr/ephyr_host_glamor.c | 60 ++++++++ 7 files changed, 396 insertions(+), 2 deletions(-) create mode 100644 glamor/glamor_core.c create mode 100644 glamor/glamor_priv.h create mode 100644 hw/kdrive/ephyr/ephyr_host_glamor.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 8f4c60758..9ed40420f 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -15,4 +15,5 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ + glamor_core.c \ glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 49771ce9d..ba2701415 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -36,12 +36,74 @@ #include -#include "glamor.h" +#include "glamor_priv.h" + +static int glamor_screen_private_key_index; +DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index; + +/** + * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable. + * + * @param drawable the drawable being requested. + * + * This function returns the backing pixmap for a drawable, whether it is a + * redirected window, unredirected window, or already a pixmap. Note that + * coordinate translation is needed when drawing to the backing pixmap of a + * redirected window, and the translation coordinates are provided by calling + * exaGetOffscreenPixmap() on the drawable. + */ +PixmapPtr +glamor_get_drawable_pixmap(DrawablePtr drawable) +{ + if (drawable->type == DRAWABLE_WINDOW) + return drawable->pScreen->GetWindowPixmap((WindowPtr)drawable); + else + return (PixmapPtr)drawable; +} + +static PixmapPtr +glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, + unsigned int usage_hint) +{ + return fbCreatePixmap(screen, w, h, depth, usage_hint); +} + +static Bool +glamor_destroy_pixmap(PixmapPtr pixmap) +{ + return fbDestroyPixmap(pixmap); +} /** Set up glamor for an already-configured GL context. */ Bool glamor_init(ScreenPtr screen) { - return Success; + glamor_screen_private *glamor_priv; + + glamor_priv = xcalloc(1, sizeof(*glamor_priv)); + if (glamor_priv == NULL) + return FALSE; + + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); + + glamor_priv->saved_create_gc = screen->CreateGC; + screen->CreateGC = glamor_create_gc; + + glamor_priv->saved_create_pixmap = screen->CreatePixmap; + screen->CreatePixmap = glamor_create_pixmap; + + glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; + screen->DestroyPixmap = glamor_destroy_pixmap; + + return TRUE; } +void +glamor_fini(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + screen->CreateGC = glamor_priv->saved_create_gc; + screen->CreatePixmap = glamor_priv->saved_create_pixmap; + screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; +} diff --git a/glamor/glamor.h b/glamor/glamor.h index e6f303845..50617b857 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -38,3 +38,4 @@ #endif /* GLAMOR_H */ Bool glamor_init(ScreenPtr screen); +void glamor_fini(ScreenPtr screen); diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c new file mode 100644 index 000000000..a894e9869 --- /dev/null +++ b/glamor/glamor_core.c @@ -0,0 +1,216 @@ +/* + * Copyright © 2001 Keith Packard + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/** @file glamor_core.c + * + * This file covers core X rendering in glamor. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "glamor_priv.h" + +static void +glamor_fill_spans(DrawablePtr drawable, GCPtr gc, int n, + DDXPointPtr points, int *width, int sorted) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + + if (1 || screen_pixmap != dest_pixmap) { + fbFillSpans(drawable, gc, n, points, width, sorted); + } else { + ErrorF("stub fill_spans\n"); + } +} + +static void +glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, + int w, int h, int leftPad, int format, char *bits) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + + if (1 || screen_pixmap != dest_pixmap) { + fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits); + } else { + ErrorF("stub put_image\n"); + } +} + +static void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *width, int n, int sorted) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + + if (1 || screen_pixmap != dest_pixmap) { + fbSetSpans(drawable, gc, src, points, width, n, sorted); + } else { + ErrorF("stub set_spans\n"); + } +} + + +/** + * glamor_poly_line() checks if it can accelerate the lines as a group of + * horizontal or vertical lines (rectangles), and uses existing rectangle fill + * acceleration if so. + */ +static void +glamor_poly_line(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + 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 || gc->lineStyle != LineSolid || + gc->fillStyle != FillSolid) { + if (1 || dest_pixmap != screen_pixmap) + fbPolyLine(drawable, gc, mode, n, points); + else + ErrorF("stub poly_line\n"); + return; + } + + rects = xalloc(sizeof(xRectangle) * (n - 1)); + x1 = points[0].x; + y1 = points[0].y; + /* If we have any non-horizontal/vertical, fall back. */ + for (i = 0; i < n - 1; i++) { + if (mode == CoordModePrevious) { + x2 = x1 + points[i + 1].x; + y2 = y1 + points[i + 1].y; + } else { + x2 = points[i + 1].x; + y2 = points[i + 1].y; + } + + if (x1 != x2 && y1 != y2) { + xfree(rects); + if (1 || dest_pixmap != screen_pixmap) + fbPolyLine(drawable, gc, mode, n, points); + else + ErrorF("stub poly_line\n"); + return; + } + + if (x1 < x2) { + rects[i].x = x1; + rects[i].width = x2 - x1 + 1; + } else { + rects[i].x = x2; + rects[i].width = x1 - x2 + 1; + } + if (y1 < y2) { + rects[i].y = y1; + rects[i].height = y2 - y1 + 1; + } else { + rects[i].y = y2; + rects[i].height = y1 - y2 + 1; + } + + x1 = x2; + y1 = y2; + } + gc->ops->PolyFillRect(drawable, gc, n - 1, rects); + xfree(rects); +} + +GCOps glamor_gc_ops = { + glamor_fill_spans, + glamor_set_spans, + glamor_put_image, + miCopyArea, + miCopyPlane, + miPolyPoint, + glamor_poly_line, + miPolySegment, + miPolyRectangle, + miPolyArc, + miFillPolygon, + miPolyFillRect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + miImageGlyphBlt, + miPolyGlyphBlt, + miPushPixels, +}; + +/** + * exaValidateGC() sets the ops to EXA's implementations, which may be + * accelerated or may sync the card and fall back to fb. + */ +static void +glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) +{ + fbValidateGC(gc, changes, drawable); + + gc->ops = &glamor_gc_ops; +} + +static GCFuncs glamor_gc_funcs = { + glamor_validate_gc, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +/** + * exaCreateGC makes a new GC and hooks up its funcs handler, so that + * exaValidateGC() will get called. + */ +int +glamor_create_gc(GCPtr gc) +{ + if (!fbCreateGC(gc)) + return FALSE; + + gc->funcs = &glamor_gc_funcs; + + return TRUE; +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h new file mode 100644 index 000000000..fe597c230 --- /dev/null +++ b/glamor/glamor_priv.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifndef GLAMOR_PRIV_H +#define GLAMOR_PRIV_H + +#include "glamor.h" + +typedef struct glamor_screen_private { + CreateGCProcPtr saved_create_gc; + CreatePixmapProcPtr saved_create_pixmap; + DestroyPixmapProcPtr saved_destroy_pixmap; +} glamor_screen_private; + +extern DevPrivateKey glamor_screen_private_key; +static inline glamor_screen_private * +glamor_get_screen_private(ScreenPtr screen) +{ + return (glamor_screen_private *)dixLookupPrivate(&screen->devPrivates, + glamor_screen_private_key); +} + +/* glamor.c */ +PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); + +/* glamor_core.c */ +Bool glamor_create_gc(GCPtr gc); + +#endif /* GLAMOR_PRIV_H */ diff --git a/hw/kdrive/ephyr/ephyr_glamor.c b/hw/kdrive/ephyr/ephyr_glamor.c index 2e2d946a9..70b466388 100644 --- a/hw/kdrive/ephyr/ephyr_glamor.c +++ b/hw/kdrive/ephyr/ephyr_glamor.c @@ -63,4 +63,5 @@ ephyr_glamor_disable(ScreenPtr screen) void ephyr_glamor_fini(ScreenPtr screen) { + glamor_fini(screen); } diff --git a/hw/kdrive/ephyr/ephyr_host_glamor.c b/hw/kdrive/ephyr/ephyr_host_glamor.c new file mode 100644 index 000000000..f652bd00e --- /dev/null +++ b/hw/kdrive/ephyr/ephyr_host_glamor.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "GL/glx.h" + +#include "hostx.h" + +void +ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) +{ + Display *dpy = hostx_get_display(); + int attribs[] = {GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None}; + XVisualInfo *visual_info; + GLXContext ctx; + + visual_info = glXChooseVisual(dpy, DefaultScreen(dpy), attribs); + if (visual_info == NULL) + errx(1, "Couldn't get RGB visual\n"); + + ctx = glXCreateContext(dpy, visual_info, NULL, True); + if (ctx == NULL) + errx(1, "glXCreateContext failed\n"); + + glXMakeCurrent(dpy, hostx_get_window(DefaultScreen(dpy)), ctx); + + XFree(visual_info); +} From b530cdea4a8e05b1f487765b8dde42cde1a6fc98 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 16 Dec 2008 15:20:49 -0800 Subject: [PATCH 006/462] glamor: Use a nicer struct initializer for gcops. --- glamor/glamor_core.c | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index a894e9869..e49e9b5ed 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -86,13 +86,13 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, /** - * glamor_poly_line() checks if it can accelerate the lines as a group of + * glamor_poly_lines() checks if it can accelerate the lines as a group of * horizontal or vertical lines (rectangles), and uses existing rectangle fill * acceleration if so. */ static void -glamor_poly_line(DrawablePtr drawable, GCPtr gc, int mode, int n, - DDXPointPtr points) +glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points) { ScreenPtr screen = drawable->pScreen; PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); @@ -156,26 +156,26 @@ glamor_poly_line(DrawablePtr drawable, GCPtr gc, int mode, int n, } GCOps glamor_gc_ops = { - glamor_fill_spans, - glamor_set_spans, - glamor_put_image, - miCopyArea, - miCopyPlane, - miPolyPoint, - glamor_poly_line, - miPolySegment, - miPolyRectangle, - miPolyArc, - miFillPolygon, - miPolyFillRect, - miPolyFillArc, - miPolyText8, - miPolyText16, - miImageText8, - miImageText16, - miImageGlyphBlt, - miPolyGlyphBlt, - miPushPixels, + .FillSpans = glamor_fill_spans, + .SetSpans = glamor_set_spans, + .PutImage = glamor_put_image, + .CopyArea = miCopyArea, + .CopyPlane = miCopyPlane, + .PolyPoint = miPolyPoint, + .Polylines = glamor_poly_lines, + .PolySegment = miPolySegment, + .PolyRectangle = miPolyRectangle, + .PolyArc = miPolyArc, + .FillPolygon = miFillPolygon, + .PolyFillRect = miPolyFillRect, + .PolyFillArc = miPolyFillArc, + .PolyText8 = miPolyText8, + .PolyText16 = miPolyText16, + .ImageText8 = miImageText8, + .ImageText16 = miImageText16, + .ImageGlyphBlt = miImageGlyphBlt, + .PolyGlyphBlt = miPolyGlyphBlt, + .PushPixels = miPushPixels, }; /** From 1b151f2e6aa581400b09220b87ae2d34a39aeb17 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 20 Dec 2008 13:48:39 -0800 Subject: [PATCH 007/462] glamor: glFlush from the blockhandler so rendering happens. --- glamor/glamor.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index ba2701415..a45745985 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -74,6 +74,18 @@ glamor_destroy_pixmap(PixmapPtr pixmap) return fbDestroyPixmap(pixmap); } +static void +glamor_block_handler(void *data, OSTimePtr wt, void *last_select_mask) +{ + glFlush(); +} + +static void +glamor_wakeup_handler(void *data, OSTimePtr wt, void *last_select_mask) +{ + glFlush(); +} + /** Set up glamor for an already-configured GL context. */ Bool glamor_init(ScreenPtr screen) @@ -86,6 +98,14 @@ glamor_init(ScreenPtr screen) dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); + if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, + glamor_wakeup_handler, + NULL)) { + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL); + xfree(glamor_priv); + return FALSE; + } + glamor_priv->saved_create_gc = screen->CreateGC; screen->CreateGC = glamor_create_gc; From df083fab84cf57fc1a2e3cd98572039bc9fe20de Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 20 Dec 2008 13:43:52 -0800 Subject: [PATCH 008/462] glamor: first real attempt at rendering. --- glamor/Makefile.am | 2 + glamor/glamor_core.c | 108 +++++++++++++++++++++++++++++++++------- glamor/glamor_priv.h | 28 +++++++++++ hw/kdrive/ephyr/ephyr.c | 5 +- 4 files changed, 125 insertions(+), 18 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 9ed40420f..b6a64fbe2 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -16,4 +16,6 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ glamor_core.c \ + glamor_fill.c \ + glamor_fillspans.c \ glamor.h diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index e49e9b5ed..eaa6b2d1e 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -36,22 +36,86 @@ #endif #include +#include "GL/gl.h" #include "glamor_priv.h" static void -glamor_fill_spans(DrawablePtr drawable, GCPtr gc, int n, - DDXPointPtr points, int *width, int sorted) +glamor_set_color_from_fgpixel(PixmapPtr pixmap, unsigned long fg_pixel) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + glColor4ub((fg_pixel >> 16) & 0xff, + (fg_pixel >> 8) & 0xff, + (fg_pixel) & 0xff, + (fg_pixel >> 24) & 0xff); +} - if (1 || screen_pixmap != dest_pixmap) { - fbFillSpans(drawable, gc, n, points, width, sorted); - } else { - ErrorF("stub fill_spans\n"); +static Bool +glamor_set_destination_pixmap(PixmapPtr pixmap) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + + if (pixmap != screen_pixmap) { + ErrorF("stubbed drawing to non-screen pixmap\n"); + return FALSE; } + + glViewport(0, 0, + screen_pixmap->drawable.width, + screen_pixmap->drawable.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, screen_pixmap->drawable.width, + 0, screen_pixmap->drawable.height, + -1.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + return TRUE; +} + +void +glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, unsigned long fg_pixel) +{ + int x1 = x; + int x2 = x + width; + int y1 = y; + int y2 = y + height; + + if (!glamor_set_destination_pixmap(pixmap)) + return; + glamor_set_color_from_fgpixel(pixmap, fg_pixel); + + glBegin(GL_TRIANGLE_FAN); + glVertex2f(x1, y1); + glVertex2f(x1, y2); + glVertex2f(x2, y2); + glVertex2f(x2, y1); + glEnd(); + + glFlush(); +} + +void +glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel, unsigned long bg_pixel, + int stipple_x, int stipple_y) +{ + ErrorF("stubbed out stipple\n"); +} + +void +glamor_tile(PixmapPtr pixmap, PixmapPtr tile, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + int tile_x, int tile_y) +{ + ErrorF("stubbed out tile\n"); } static void @@ -62,7 +126,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - if (1 || screen_pixmap != dest_pixmap) { + if (screen_pixmap != dest_pixmap) { fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits); } else { ErrorF("stub put_image\n"); @@ -71,20 +135,30 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, static void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *width, int n, int sorted) + DDXPointPtr points, int *widths, int n, int sorted) { ScreenPtr screen = drawable->pScreen; PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - if (1 || screen_pixmap != dest_pixmap) { - fbSetSpans(drawable, gc, src, points, width, n, sorted); + if (screen_pixmap != dest_pixmap) { + fbSetSpans(drawable, gc, src, points, widths, n, sorted); } else { - ErrorF("stub set_spans\n"); + int i; + + if (!glamor_set_destination_pixmap(dest_pixmap)) + return; + for (i = 0; i < n; i++) { + glDrawPixels(points[i].x - dest_pixmap->screen_x, + points[i].y - dest_pixmap->screen_y, + widths[i], + 1, + src); + src += PixmapBytePad(widths[i], drawable->depth); + } } } - /** * glamor_poly_lines() checks if it can accelerate the lines as a group of * horizontal or vertical lines (rectangles), and uses existing rectangle fill @@ -104,7 +178,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0 || gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { - if (1 || dest_pixmap != screen_pixmap) + if (dest_pixmap != screen_pixmap) fbPolyLine(drawable, gc, mode, n, points); else ErrorF("stub poly_line\n"); @@ -126,7 +200,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, if (x1 != x2 && y1 != y2) { xfree(rects); - if (1 || dest_pixmap != screen_pixmap) + if (dest_pixmap != screen_pixmap) fbPolyLine(drawable, gc, mode, n, points); else ErrorF("stub poly_line\n"); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index fe597c230..ef043d035 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -49,5 +49,33 @@ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); /* glamor_core.c */ Bool glamor_create_gc(GCPtr gc); +void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel); +void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel, unsigned long bg_pixel, + int stipple_x, int stipple_y); +void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + int tile_x, int tile_y); + +/* glamor_fill.c */ +void glamor_fill(DrawablePtr drawable, + GCPtr gc, + int x, + int y, + int width, + int height); + +/* glamor_fillspans.c */ +void glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, + DDXPointPtr points, + int *widths, + int sorted); #endif /* GLAMOR_PRIV_H */ diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 7ebf1c253..16959d74b 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -394,7 +394,10 @@ ephyrSetInternalDamage (ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; PixmapPtr pPixmap = NULL; - + + if (ephyrFuncs.initAccel == ephyr_glamor_init) + return TRUE; + scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0, (DamageDestroyFunc) 0, DamageReportNone, From e32efb02e5dff9124e8680f9a15d9d2b01db84c7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 20 Dec 2008 14:48:18 -0800 Subject: [PATCH 009/462] ephyr: merge the host glamor bits into hostx. --- hw/kdrive/ephyr/Makefile.am | 3 +- hw/kdrive/ephyr/ephyr_host_glamor.c | 60 ----------------------------- hw/kdrive/ephyr/hostx.c | 35 +++++++++++++++++ 3 files changed, 36 insertions(+), 62 deletions(-) delete mode 100644 hw/kdrive/ephyr/ephyr_host_glamor.c diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 349e86dca..7e10d6b79 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -24,8 +24,7 @@ bin_PROGRAMS = Xephyr HOSTX_SRCS = \ hostx.c \ - hostx.h \ - ephyr_host_glamor.c + hostx.h HOSTVIDEO_SRCS = \ ephyrvideo.c \ diff --git a/hw/kdrive/ephyr/ephyr_host_glamor.c b/hw/kdrive/ephyr/ephyr_host_glamor.c deleted file mode 100644 index f652bd00e..000000000 --- a/hw/kdrive/ephyr/ephyr_host_glamor.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright © 2008 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "GL/glx.h" - -#include "hostx.h" - -void -ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) -{ - Display *dpy = hostx_get_display(); - int attribs[] = {GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - None}; - XVisualInfo *visual_info; - GLXContext ctx; - - visual_info = glXChooseVisual(dpy, DefaultScreen(dpy), attribs); - if (visual_info == NULL) - errx(1, "Couldn't get RGB visual\n"); - - ctx = glXCreateContext(dpy, visual_info, NULL, True); - if (ctx == NULL) - errx(1, "glXCreateContext failed\n"); - - glXMakeCurrent(dpy, hostx_get_window(DefaultScreen(dpy)), ctx); - - XFree(visual_info); -} diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 4caf4516d..a854c881d 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -46,6 +46,7 @@ #include #include /* for memset */ #include +#include #include #include @@ -61,6 +62,7 @@ #include #endif /* XF86DRI */ #include "ephyrlog.h" +#include "GL/glx.h" #ifdef XF86DRI extern Bool XF86DRIQueryExtension (Display *dpy, @@ -1445,3 +1447,36 @@ hostx_has_glx (void) } #endif /* XF86DRI */ + +void +ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) +{ + Display *dpy = hostx_get_display(); + int attribs[] = {GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None}; + XVisualInfo *visual_info; + GLXContext ctx; + struct EphyrHostScreen *host_screen; + int event_base = 0, error_base = 0; + + host_screen = host_screen_from_screen_info(ephyr_screen); + + if (!glXQueryExtension (dpy, &event_base, &error_base)) + errx(1, "Couldn't find GLX extension\n"); + + visual_info = glXChooseVisual(dpy, DefaultScreen(dpy), attribs); + if (visual_info == NULL) + errx(1, "Couldn't get RGB visual\n"); + + ctx = glXCreateContext(dpy, visual_info, NULL, True); + if (ctx == NULL) + errx(1, "glXCreateContext failed\n"); + + if (!glXMakeCurrent(dpy, host_screen->win, ctx)) + errx(1, "glXMakeCurrent failed\n"); + + XFree(visual_info); +} From 08097434ecc6479dc69a408523f398284168697e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 09:10:12 -0700 Subject: [PATCH 010/462] add fill files, merge with first real attempt at rendering. --- glamor/glamor_fill.c | 84 +++++++++++++++++++++++++++++ glamor/glamor_fillspans.c | 108 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 glamor/glamor_fill.c create mode 100644 glamor/glamor_fillspans.c diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c new file mode 100644 index 000000000..36e7badfb --- /dev/null +++ b/glamor/glamor_fill.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2008 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_fillspans.c + * + * GC fill implementation, based loosely on fb_fill.c + */ + +void +glamor_fill(DrawablePtr drawable, + GCPtr gc, + int x, + int y, + int width, + int height) +{ + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); + + switch (gc->fillStyle) { + case FillSolid: + glamor_solid(dst_pixmap, + x - dst_pixmap->screen_x, + y - dst_pixmap->screen_y, + width, + height, + gc->alu, + gc->planemask, + gc->fgPixel); + break; + case FillStippled: + case FillOpaqueStippled: + glamor_stipple(dst_pixmap, + gc->stipple, + x - dst_pixmap->screen_x, + y - dst_pixmap->screen_y, + width, + height, + gc->alu, + gc->planemask, + gc->fgPixel, + gc->bgPixel, + gc->patOrg.x - dst_pixmap->screen_x, + gc->patOrg.y - dst_pixmap->screen_y); + break; + case FillTiled: + glamor_tile(dst_pixmap, + gc->tile.pixmap, + x - dst_pixmap->screen_x, + y - dst_pixmap->screen_y, + width, + height, + gc->alu, + gc->planemask, + gc->patOrg.x - dst_pixmap->screen_y, + gc->patOrg.y - dst_pixmap->screen_y); + break; + } +} diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c new file mode 100644 index 000000000..b0b704fd9 --- /dev/null +++ b/glamor/glamor_fillspans.c @@ -0,0 +1,108 @@ +/* + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +/** @file glamor_fillspans.c + * + * FillSpans implementation, taken from fb_fillsp.c + */ +#include "glamor_priv.h" + +void +glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, + DDXPointPtr points, + int *widths, + int sorted) +{ + RegionPtr clip = gc->pCompositeClip; + BoxPtr extents, boxes; + int nbox; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1; + int partX1, partX2; + ScreenPtr screen = drawable->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + + if (dest_pixmap != screen_pixmap) { + fbFillSpans(drawable, gc, n, points, widths, sorted); + return; + } + + extents = REGION_EXTENTS(gc->pScreen, clip); + extentX1 = extents->x1; + extentY1 = extents->y1; + extentX2 = extents->x2; + extentY2 = extents->y2; + while (n--) { + fullX1 = points->x; + fullY1 = points->y; + fullX2 = fullX1 + *widths; + points++; + widths++; + + if (fullY1 < extentY1 || extentY2 <= fullY1) + continue; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullX1 >= fullX2) + continue; + + nbox = REGION_NUM_RECTS (clip); + if (nbox == 1) { + glamor_fill(drawable, + gc, + fullX1, fullY1, fullX2-fullX1, 1); + } else { + boxes = REGION_RECTS(clip); + while(nbox--) + { + if (boxes->y1 <= fullY1 && fullY1 < boxes->y2) + { + partX1 = boxes->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partX2 = boxes->x2; + if (partX2 > fullX2) + partX2 = fullX2; + if (partX2 > partX1) + { + glamor_fill(drawable, gc, + partX1, fullY1, + partX2 - partX1, 1); + } + } + boxes++; + } + } + } +} From 370df817ac0b346f1c7aa0b6e823c77797caaa9f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 09:35:24 -0700 Subject: [PATCH 011/462] ephyr: Make sure a glamor-using window is created with a glx visual. --- hw/kdrive/ephyr/ephyrinit.c | 2 ++ hw/kdrive/ephyr/hostx.c | 39 +++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 4b291813a..9155d0861 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -31,6 +31,7 @@ extern Window EphyrPreExistingHostWin; extern Bool EphyrWantGrayScale; +extern Bool ephyr_glamor; extern Bool kdHasPointer; extern Bool kdHasKbd; @@ -223,6 +224,7 @@ ddxProcessArgument (int argc, char **argv, int i) } else if (!strcmp (argv[i], "-glamor")) { + ephyr_glamor = TRUE; ephyrFuncs.initAccel = ephyr_glamor_init; ephyrFuncs.enableAccel = ephyr_glamor_enable; ephyrFuncs.disableAccel = ephyr_glamor_disable; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index a854c881d..c7c792984 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -97,6 +97,7 @@ struct EphyrHostXVars Display *dpy; int screen; Visual *visual; + XVisualInfo *visual_info; Window winroot; GC gc; int depth; @@ -125,10 +126,14 @@ extern int monitorResolution; char *ephyrResName = NULL; int ephyrResNameFromCmd = 0; char *ephyrTitle = NULL; +Bool ephyr_glamor = FALSE; static void hostx_set_fullscreen_hint(void); +static void +ephyr_glamor_get_visual(void); + /* X Error traps */ static int trapped_error_code = 0; @@ -364,8 +369,11 @@ hostx_init (void) HostX.winroot = RootWindow(HostX.dpy, HostX.screen); HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); HostX.depth = DefaultDepth(HostX.dpy, HostX.screen); - HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); - + if (ephyr_glamor) { + ephyr_glamor_get_visual(); + } else { + HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); + } class_hint = XAllocClassHint(); for (index = 0 ; index < HostX.n_screens ; index++) @@ -1448,22 +1456,18 @@ hostx_has_glx (void) #endif /* XF86DRI */ -void -ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) +static void +ephyr_glamor_get_visual(void) { - Display *dpy = hostx_get_display(); + Display *dpy = HostX.dpy; int attribs[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None}; XVisualInfo *visual_info; - GLXContext ctx; - struct EphyrHostScreen *host_screen; int event_base = 0, error_base = 0; - host_screen = host_screen_from_screen_info(ephyr_screen); - if (!glXQueryExtension (dpy, &event_base, &error_base)) errx(1, "Couldn't find GLX extension\n"); @@ -1471,12 +1475,23 @@ ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) if (visual_info == NULL) errx(1, "Couldn't get RGB visual\n"); - ctx = glXCreateContext(dpy, visual_info, NULL, True); + HostX.visual_info = visual_info; + HostX.visual = visual_info->visual; +} + +void +ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) +{ + Display *dpy = HostX.dpy; + GLXContext ctx; + struct EphyrHostScreen *host_screen; + + host_screen = host_screen_from_screen_info(ephyr_screen); + + ctx = glXCreateContext(dpy, HostX.visual_info, NULL, True); if (ctx == NULL) errx(1, "glXCreateContext failed\n"); if (!glXMakeCurrent(dpy, host_screen->win, ctx)) errx(1, "glXMakeCurrent failed\n"); - - XFree(visual_info); } From 2e35ceca65bbebf07c15ea2cff932a8749955c2b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 11:19:43 -0700 Subject: [PATCH 012/462] ephyr: Use GLEW. This will hide all sorts of extension stuff from us. --- configure.ac | 9 +++++++++ glamor/glamor.c | 2 ++ glamor/glamor_core.c | 1 - glamor/glamor_priv.h | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 10069be66..3954ecc06 100644 --- a/configure.ac +++ b/configure.ac @@ -2011,6 +2011,15 @@ if test "$KDRIVE" = yes; then AC_MSG_ERROR([Xephyr dependencies missing]) fi + AC_CHECK_LIB(GLEW, glewInit, [ + AC_CHECK_HEADER(GL/glew.h, [], [ + AC_MSG_ERROR([requires glew http://glew.sourceforge.net/]) + ]) + ], [ + AC_MSG_ERROR([requires glew http://glew.sourceforge.net/]) + ]) + XEPHYR_LIBS="$XEPHYR_LIBS -lGLEW" + # Xephyr needs nanosleep() which is in librt on Solaris AC_CHECK_FUNC([nanosleep], [], AC_CHECK_LIB([rt], [nanosleep], XEPHYR_LIBS="$XEPHYR_LIBS -lrt")) diff --git a/glamor/glamor.c b/glamor/glamor.c index a45745985..08e7ff966 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -115,6 +115,8 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; + glewInit(); + return TRUE; } diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index eaa6b2d1e..651414b6e 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -36,7 +36,6 @@ #endif #include -#include "GL/gl.h" #include "glamor_priv.h" diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index ef043d035..285799da5 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -29,6 +29,7 @@ #define GLAMOR_PRIV_H #include "glamor.h" +#include typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; From 399e00698976dd2e503b3a092bfe54ab24ea26d9 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 11:37:37 -0700 Subject: [PATCH 013/462] glamor: Fix up block/wakeup handler. Prototypes are fixed, and we don't need to flush on wakeup. --- glamor/glamor.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 08e7ff966..86a76940e 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -75,15 +75,14 @@ glamor_destroy_pixmap(PixmapPtr pixmap) } static void -glamor_block_handler(void *data, OSTimePtr wt, void *last_select_mask) +glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask) { glFlush(); } static void -glamor_wakeup_handler(void *data, OSTimePtr wt, void *last_select_mask) +glamor_wakeup_handler(void *data, int result, void *last_select_mask) { - glFlush(); } /** Set up glamor for an already-configured GL context. */ From 74f262bcdb3d8ae769ef8975cf4a4b2ebaeb6b39 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 11:39:05 -0700 Subject: [PATCH 014/462] glamor: remove gratuitous flush. --- glamor/glamor_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 651414b6e..39f36cd9b 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -94,8 +94,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glVertex2f(x2, y2); glVertex2f(x2, y1); glEnd(); - - glFlush(); } void From fbbdd788cbc822fc8a2d2726435bfa39e69a0e85 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 12:36:33 -0700 Subject: [PATCH 015/462] glamor: Fix up DrawPixels arguments to bear some relation to reality. --- glamor/glamor_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 39f36cd9b..7f97190cc 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -146,10 +146,11 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (!glamor_set_destination_pixmap(dest_pixmap)) return; for (i = 0; i < n; i++) { - glDrawPixels(points[i].x - dest_pixmap->screen_x, - points[i].y - dest_pixmap->screen_y, - widths[i], + glRasterPos2i(points[i].x - dest_pixmap->screen_x, + points[i].y - dest_pixmap->screen_y); + glDrawPixels(widths[i], 1, + GL_RGBA, GL_UNSIGNED_BYTE, src); src += PixmapBytePad(widths[i], drawable->depth); } From f1dbed5456e5a608425530e0dde2dc617a7c6115 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 12:32:53 -0700 Subject: [PATCH 016/462] glamor: Move to using shader objects. --- glamor/glamor.c | 22 ++++++-- glamor/glamor_core.c | 125 +++++++++++++++++++++++++++++++------------ glamor/glamor_fill.c | 86 +++++++++++++++++++++++++++++ glamor/glamor_priv.h | 29 ++++++++-- 4 files changed, 221 insertions(+), 41 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 86a76940e..050dd3d66 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -97,12 +97,21 @@ glamor_init(ScreenPtr screen) dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); + glewInit(); + + if (!GLEW_ARB_shader_objects) { + ErrorF("GL_ARB_shader_objects required\n"); + goto fail; + } + if (!GLEW_ARB_vertex_shader) { + ErrorF("GL_ARB_vertex_shader required\n"); + goto fail; + } + if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, NULL)) { - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL); - xfree(glamor_priv); - return FALSE; + goto fail; } glamor_priv->saved_create_gc = screen->CreateGC; @@ -114,9 +123,14 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; - glewInit(); + glamor_init_solid_shader(screen); return TRUE; + +fail: + xfree(glamor_priv); + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL); + return FALSE; } void diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 7f97190cc..9c892ead9 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -39,16 +39,7 @@ #include "glamor_priv.h" -static void -glamor_set_color_from_fgpixel(PixmapPtr pixmap, unsigned long fg_pixel) -{ - glColor4ub((fg_pixel >> 16) & 0xff, - (fg_pixel >> 8) & 0xff, - (fg_pixel) & 0xff, - (fg_pixel >> 24) & 0xff); -} - -static Bool +Bool glamor_set_destination_pixmap(PixmapPtr pixmap) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -63,37 +54,103 @@ glamor_set_destination_pixmap(PixmapPtr pixmap) screen_pixmap->drawable.width, screen_pixmap->drawable.height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, screen_pixmap->drawable.width, - 0, screen_pixmap->drawable.height, - -1.0, 1.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - return TRUE; } void -glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, unsigned long fg_pixel) +glamor_get_transform_uniform_locations(GLint prog, + glamor_transform_uniforms *uniform_locations) { - int x1 = x; - int x2 = x + width; - int y1 = y; - int y2 = y + height; + 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"); +} - if (!glamor_set_destination_pixmap(pixmap)) - return; - glamor_set_color_from_fgpixel(pixmap, fg_pixel); +/* We don't use a full matrix for our transformations because it's + * wasteful when all we want is to rescale to NDC and possibly do a flip + * if it's the front buffer. + */ +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); +} - glBegin(GL_TRIANGLE_FAN); - glVertex2f(x1, y1); - glVertex2f(x1, y2); - glVertex2f(x2, y2); - glVertex2f(x2, y1); - glEnd(); +GLint +glamor_compile_glsl_prog(GLenum type, const char *source) +{ + 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; + + 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"); + } + + return prog; +} + +void +glamor_link_glsl_prog(GLint prog) +{ + GLint ok; + + 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); + + 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) +{ + if (pixmap->drawable.depth < 24) { + ErrorF("pixmap with bad depth\n"); + color[0] = 1.0; + color[1] = 0.0; + color[2] = 1.0; + color[3] = 1.0; + } else { + color[0] = ubyte_to_float(fg_pixel >> 16); + color[1] = ubyte_to_float(fg_pixel >> 8); + color[2] = ubyte_to_float(fg_pixel >> 0); + color[3] = ubyte_to_float(fg_pixel >> 24); + } } void diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 36e7badfb..0d87bd037 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -82,3 +82,89 @@ glamor_fill(DrawablePtr drawable, break; } } + +void +glamor_init_solid_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + const char *solid_vs_only = + "uniform vec4 color;\n" + "uniform float x_bias;\n" + "uniform float x_scale;\n" + "uniform float y_bias;\n" + "uniform float y_scale;\n" + "void main()\n" + "{\n" + " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" + " (gl_Vertex.y + y_bias) * y_scale,\n" + " 0,\n" + " 1);\n" + " gl_Color = color;\n" + "}\n"; + const char *solid_vs = + "uniform float x_bias;\n" + "uniform float x_scale;\n" + "uniform float y_bias;\n" + "uniform float y_scale;\n" + "void main()\n" + "{\n" + " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" + " (gl_Vertex.y + y_bias) * y_scale,\n" + " 0,\n" + " 1);\n" + "}\n"; + const char *solid_fs = + "uniform vec4 color;\n" + "void main()\n" + "{\n" + " gl_FragColor = color;\n" + "}\n"; + GLint fs_prog, vs_prog; + + glamor_priv->solid_prog = glCreateProgramObjectARB(); + if (GLEW_ARB_fragment_shader) { + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, solid_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, solid_fs); + glAttachObjectARB(glamor_priv->solid_prog, vs_prog); + glAttachObjectARB(glamor_priv->solid_prog, fs_prog); + } else { + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, solid_vs_only); + glAttachObjectARB(glamor_priv->solid_prog, vs_prog); + } + glamor_link_glsl_prog(glamor_priv->solid_prog); + + glamor_priv->solid_color_uniform_location = + glGetUniformLocationARB(glamor_priv->solid_prog, "color"); + glamor_get_transform_uniform_locations(glamor_priv->solid_prog, + &glamor_priv->solid_transform); +} + +void +glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, unsigned long fg_pixel) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + int x1 = x; + int x2 = x + width; + int y1 = y; + int y2 = y + height; + GLfloat color[4]; + + if (!glamor_set_destination_pixmap(pixmap)) + return; + + glUseProgramObjectARB(glamor_priv->solid_prog); + glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); + glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color); + glamor_set_transform_for_pixmap(pixmap, &glamor_priv->solid_transform); + + glBegin(GL_TRIANGLE_FAN); + glVertex2f(x1, y1); + glVertex2f(x1, y2); + glVertex2f(x2, y2); + glVertex2f(x2, y1); + glEnd(); + + glUseProgramObjectARB(0); +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 285799da5..3216a7a4a 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -31,10 +31,22 @@ #include "glamor.h" #include +typedef struct glamor_transform_uniforms { + GLint x_bias; + GLint x_scale; + GLint y_bias; + GLint y_scale; +} glamor_transform_uniforms; + typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; DestroyPixmapProcPtr saved_destroy_pixmap; + + /* glamor_solid */ + GLint solid_prog; + GLint solid_color_uniform_location; + glamor_transform_uniforms solid_transform; } glamor_screen_private; extern DevPrivateKey glamor_screen_private_key; @@ -50,9 +62,6 @@ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); /* glamor_core.c */ Bool glamor_create_gc(GCPtr gc); -void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, - unsigned long fg_pixel); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, @@ -62,6 +71,15 @@ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, int tile_x, int tile_y); +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); +void glamor_get_transform_uniform_locations(GLint prog, + glamor_transform_uniforms *uniform_locations); +void glamor_set_transform_for_pixmap(PixmapPtr pixmap, + glamor_transform_uniforms *uniform_locations); /* glamor_fill.c */ void glamor_fill(DrawablePtr drawable, @@ -70,6 +88,9 @@ void glamor_fill(DrawablePtr drawable, int y, int width, int height); +void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel); /* glamor_fillspans.c */ void glamor_fill_spans(DrawablePtr drawable, @@ -79,4 +100,6 @@ void glamor_fill_spans(DrawablePtr drawable, int *widths, int sorted); +void glamor_init_solid_shader(ScreenPtr screen); + #endif /* GLAMOR_PRIV_H */ From 4f139db92fb283792adae8d39a49a083e4382fb5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 14:43:43 -0700 Subject: [PATCH 017/462] glamor: Add getspans implementation. --- glamor/Makefile.am | 1 + glamor/glamor.c | 4 +++ glamor/glamor_getspans.c | 74 ++++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 10 ++++++ 4 files changed, 89 insertions(+) create mode 100644 glamor/glamor_getspans.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index b6a64fbe2..2d9fdf57c 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -18,4 +18,5 @@ libglamor_la_SOURCES = \ glamor_core.c \ glamor_fill.c \ glamor_fillspans.c \ + glamor_getspans.c \ glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 050dd3d66..0aa9db83b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -123,6 +123,9 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; + glamor_priv->saved_get_spans = screen->GetSpans; + screen->GetSpans = glamor_get_spans; + glamor_init_solid_shader(screen); return TRUE; @@ -141,4 +144,5 @@ glamor_fini(ScreenPtr screen) screen->CreateGC = glamor_priv->saved_create_gc; screen->CreatePixmap = glamor_priv->saved_create_pixmap; screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; + screen->GetSpans = glamor_priv->saved_get_spans; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c new file mode 100644 index 000000000..b10a29dcd --- /dev/null +++ b/glamor/glamor_getspans.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +void +glamor_get_spans(DrawablePtr drawable, + int wmax, + DDXPointPtr points, + int *widths, + int count, + char *dst) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + + if (screen_pixmap != pixmap) { + fbGetSpans(drawable, wmax, points, widths, count, dst); + return; + } else { + GLenum format, type; + int i; + switch (drawable->depth) { + case 24: + case 32: + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + default: + ErrorF("Unknown getspans depth %d\n", drawable->depth); + return; + } + if (!glamor_set_destination_pixmap(pixmap)) + return; + for (i = 0; i < count; i++) { + glReadPixels(points[i].x - pixmap->screen_x, + points[i].y - pixmap->screen_y, + widths[i], + 1, + format, type, + dst); + dst += PixmapBytePad(widths[i], drawable->depth); + } + } +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3216a7a4a..016a404bc 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -42,6 +42,7 @@ typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; DestroyPixmapProcPtr saved_destroy_pixmap; + GetSpansProcPtr saved_get_spans; /* glamor_solid */ GLint solid_prog; @@ -102,4 +103,13 @@ void glamor_fill_spans(DrawablePtr drawable, void glamor_init_solid_shader(ScreenPtr screen); +/* glamor_getspans.c */ +void +glamor_get_spans(DrawablePtr drawable, + int wmax, + DDXPointPtr points, + int *widths, + int nspans, + char *dst_start); + #endif /* GLAMOR_PRIV_H */ From f92d1478e984d57806731886820f47e1258b5115 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 14:45:47 -0700 Subject: [PATCH 018/462] glamor: Maybe fix up the format/type for setspans. --- glamor/glamor_core.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 9c892ead9..c8b331a18 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -198,8 +198,20 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (screen_pixmap != dest_pixmap) { fbSetSpans(drawable, gc, src, points, widths, n, sorted); } else { + GLenum format, type; int i; + switch (drawable->depth) { + case 24: + case 32: + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + default: + ErrorF("Unknown setspans depth %d\n", drawable->depth); + return; + } + if (!glamor_set_destination_pixmap(dest_pixmap)) return; for (i = 0; i < n; i++) { @@ -207,7 +219,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, points[i].y - dest_pixmap->screen_y); glDrawPixels(widths[i], 1, - GL_RGBA, GL_UNSIGNED_BYTE, + format, type, src); src += PixmapBytePad(widths[i], drawable->depth); } From 519103565c1b182014dea93c58917bf7e5a35fcb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 15:28:13 -0700 Subject: [PATCH 019/462] glamor: Create FBOs for pixmaps. --- glamor/glamor.c | 64 ++++++++++++++++++++++- glamor/glamor_core.c | 107 ++++++++++++++++++-------------------- glamor/glamor_fillspans.c | 8 --- glamor/glamor_getspans.c | 51 +++++++++--------- glamor/glamor_priv.h | 11 ++++ 5 files changed, 148 insertions(+), 93 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 0aa9db83b..7b81abab2 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -40,6 +40,8 @@ static int glamor_screen_private_key_index; DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index; +static int glamor_pixmap_private_key_index; +DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index; /** * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable. @@ -63,9 +65,57 @@ glamor_get_drawable_pixmap(DrawablePtr drawable) static PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, - unsigned int usage_hint) + unsigned int usage) { - return fbCreatePixmap(screen, w, h, depth, usage_hint); + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + GLenum format; + + if (w > 32767 || h > 32767) + return NullPixmap; + + pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (w == 0 || h == 0) + return pixmap; + + /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. + * FBOs, which EXT_fbo forgot to do. + */ + switch (depth) { + case 24: + format = GL_RGB; + break; + default: + format = GL_RGBA; + break; + } + + /* Create the texture used to store the pixmap's data. */ + glGenTextures(1, &pixmap_priv->tex); + glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + 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, format, w, h, 0, + format, GL_UNSIGNED_BYTE, NULL); + + /* Create a framebuffer object wrapping the texture so that we can render + * to it. + */ + 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); + + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + (w * pixmap->drawable.bitsPerPixel + 7) / 8, + NULL); + + return pixmap; } static Bool @@ -96,9 +146,19 @@ glamor_init(ScreenPtr screen) return FALSE; dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); + if (!dixRequestPrivate(glamor_pixmap_private_key, + sizeof(glamor_pixmap_private))) { + LogMessage(X_WARNING, + "glamor%d: Failed to allocate pixmap private\n", + screen->myNum); + } glewInit(); + if (!GLEW_EXT_framebuffer_object) { + ErrorF("GL_EXT_framebuffer_object required\n"); + goto fail; + } if (!GLEW_ARB_shader_objects) { ErrorF("GL_ARB_shader_objects required\n"); goto fail; diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index c8b331a18..ffccd3e12 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -42,17 +42,28 @@ Bool glamor_set_destination_pixmap(PixmapPtr pixmap) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap != screen_pixmap) { - ErrorF("stubbed drawing to non-screen pixmap\n"); + if (pixmap_priv == NULL) { + ErrorF("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) { + ErrorF("No FBO\n"); + return FALSE; + } + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glViewport(0, 0, - screen_pixmap->drawable.width, - screen_pixmap->drawable.height); + pixmap->drawable.width, + pixmap->drawable.height); return TRUE; } @@ -75,10 +86,18 @@ void glamor_set_transform_for_pixmap(PixmapPtr pixmap, glamor_transform_uniforms *uniform_locations) { + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + 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); + if (pixmap == screen_pixmap) + glUniform1fARB(uniform_locations->y_scale, + -2.0f / pixmap->drawable.height); + else + glUniform1fARB(uniform_locations->y_scale, + 2.0f / pixmap->drawable.height); } GLint @@ -176,53 +195,38 @@ static void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - - if (screen_pixmap != dest_pixmap) { - fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits); - } else { - ErrorF("stub put_image\n"); - } + ErrorF("stub put_image\n"); } static void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + GLenum format, type; + int i; - if (screen_pixmap != dest_pixmap) { - fbSetSpans(drawable, gc, src, points, widths, n, sorted); - } else { - GLenum format, type; - int i; + switch (drawable->depth) { + case 24: + case 32: + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + default: + ErrorF("Unknown setspans depth %d\n", drawable->depth); + return; + } - switch (drawable->depth) { - case 24: - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - ErrorF("Unknown setspans depth %d\n", drawable->depth); - return; - } - - if (!glamor_set_destination_pixmap(dest_pixmap)) - return; - for (i = 0; i < n; i++) { - glRasterPos2i(points[i].x - dest_pixmap->screen_x, - points[i].y - dest_pixmap->screen_y); - glDrawPixels(widths[i], - 1, - format, type, - src); - src += PixmapBytePad(widths[i], drawable->depth); - } + if (!glamor_set_destination_pixmap(dest_pixmap)) + return; + for (i = 0; i < n; i++) { + glRasterPos2i(points[i].x - dest_pixmap->screen_x, + points[i].y - dest_pixmap->screen_y); + glDrawPixels(widths[i], + 1, + format, type, + src); + src += PixmapBytePad(widths[i], drawable->depth); } } @@ -235,9 +239,6 @@ static void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); xRectangle *rects; int x1, x2, y1, y2; int i; @@ -245,10 +246,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0 || gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { - if (dest_pixmap != screen_pixmap) - fbPolyLine(drawable, gc, mode, n, points); - else - ErrorF("stub poly_line\n"); + ErrorF("stub poly_line\n"); return; } @@ -267,10 +265,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, if (x1 != x2 && y1 != y2) { xfree(rects); - if (dest_pixmap != screen_pixmap) - fbPolyLine(drawable, gc, mode, n, points); - else - ErrorF("stub poly_line\n"); + ErrorF("stub poly_line\n"); return; } diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index b0b704fd9..120e3467d 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -44,14 +44,6 @@ glamor_fill_spans(DrawablePtr drawable, int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; int partX1, partX2; - ScreenPtr screen = drawable->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - - if (dest_pixmap != screen_pixmap) { - fbFillSpans(drawable, gc, n, points, widths, sorted); - return; - } extents = REGION_EXTENTS(gc->pScreen, clip); extentX1 = extents->x1; diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index b10a29dcd..8466208d7 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -39,36 +39,33 @@ glamor_get_spans(DrawablePtr drawable, int count, char *dst) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + GLenum format, type; + int i; - if (screen_pixmap != pixmap) { + switch (drawable->depth) { + case 24: + case 32: + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + default: + ErrorF("Unknown getspans depth %d\n", drawable->depth); + return; + } + + if (!glamor_set_destination_pixmap(pixmap)) { fbGetSpans(drawable, wmax, points, widths, count, dst); return; - } else { - GLenum format, type; - int i; - switch (drawable->depth) { - case 24: - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - ErrorF("Unknown getspans depth %d\n", drawable->depth); - return; - } - if (!glamor_set_destination_pixmap(pixmap)) - return; - for (i = 0; i < count; i++) { - glReadPixels(points[i].x - pixmap->screen_x, - points[i].y - pixmap->screen_y, - widths[i], - 1, - format, type, - dst); - dst += PixmapBytePad(widths[i], drawable->depth); - } + } + + for (i = 0; i < count; i++) { + glReadPixels(points[i].x - pixmap->screen_x, + points[i].y - pixmap->screen_y, + widths[i], + 1, + format, type, + dst); + dst += PixmapBytePad(widths[i], drawable->depth); } } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 016a404bc..6d08b00c6 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -50,13 +50,24 @@ typedef struct glamor_screen_private { glamor_transform_uniforms solid_transform; } glamor_screen_private; +typedef struct glamor_pixmap_private { + GLuint tex; + GLuint fb; +} glamor_pixmap_private; + 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); } +static inline glamor_pixmap_private * +glamor_get_pixmap_private(PixmapPtr pixmap) +{ + return dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); +} /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); From 8016135ec7616530e64d0019ce0401e62b25e483 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 15:37:22 -0700 Subject: [PATCH 020/462] glamor: Fill out glamor_get_color_4f_from_pixel() a bit. --- glamor/glamor_core.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index ffccd3e12..e4aa95dbc 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -158,17 +158,33 @@ void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, GLfloat *color) { - if (pixmap->drawable.depth < 24) { - ErrorF("pixmap with bad depth\n"); - color[0] = 1.0; + switch (pixmap->drawable.depth) { + case 1: + color[0] = 0.0; color[1] = 0.0; - color[2] = 1.0; - color[3] = 1.0; - } else { + 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); color[1] = ubyte_to_float(fg_pixel >> 8); color[2] = ubyte_to_float(fg_pixel >> 0); color[3] = ubyte_to_float(fg_pixel >> 24); + 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; } } From 16c3b929dd4cae6b40e847256db6ff32e63e9029 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 16:06:42 -0700 Subject: [PATCH 021/462] glamor: Add untested support for tile filling. --- glamor/Makefile.am | 1 + glamor/glamor.c | 1 + glamor/glamor_core.c | 9 --- glamor/glamor_fill.c | 20 ++++++ glamor/glamor_priv.h | 27 ++++++-- glamor/glamor_tile.c | 151 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 glamor/glamor_tile.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 2d9fdf57c..2453566fc 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -19,4 +19,5 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ + glamor_tile.c \ glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 7b81abab2..c3e4eb9f8 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -187,6 +187,7 @@ glamor_init(ScreenPtr screen) screen->GetSpans = glamor_get_spans; glamor_init_solid_shader(screen); + glamor_init_tile_shader(screen); return TRUE; diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index e4aa95dbc..549a5f313 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -198,15 +198,6 @@ glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, ErrorF("stubbed out stipple\n"); } -void -glamor_tile(PixmapPtr pixmap, PixmapPtr tile, - int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, - int tile_x, int tile_y) -{ - ErrorF("stubbed out tile\n"); -} - static void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 0d87bd037..11d5f9841 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -168,3 +168,23 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glUseProgramObjectARB(0); } + +/* 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_priv.h b/glamor/glamor_priv.h index 6d08b00c6..9bae8144b 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -48,6 +48,9 @@ typedef struct glamor_screen_private { GLint solid_prog; GLint solid_color_uniform_location; glamor_transform_uniforms solid_transform; + + GLint tile_prog; + glamor_transform_uniforms tile_transform; } glamor_screen_private; typedef struct glamor_pixmap_private { @@ -69,6 +72,17 @@ glamor_get_pixmap_private(PixmapPtr pixmap) return dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); } +/** + * Returns TRUE if the given planemask covers all the significant bits in the + * pixel values for pDrawable. + */ +static inline Bool +glamor_pm_is_solid(DrawablePtr drawable, unsigned long planemask) +{ + return (planemask & FbFullMask(drawable->depth)) == + FbFullMask(drawable->depth); +} + /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); @@ -79,10 +93,6 @@ void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, unsigned char alu, unsigned long planemask, unsigned long fg_pixel, unsigned long bg_pixel, int stipple_x, int stipple_y); -void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, - int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, - int tile_x, int tile_y); 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, @@ -103,6 +113,8 @@ void glamor_fill(DrawablePtr drawable, void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel); +void glamor_solid_fail_region(PixmapPtr pixmap, + int x, int y, int width, int height); /* glamor_fillspans.c */ void glamor_fill_spans(DrawablePtr drawable, @@ -123,4 +135,11 @@ glamor_get_spans(DrawablePtr drawable, int nspans, char *dst_start); +/* glamor_tile.c */ +void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + int tile_x, int tile_y); +void glamor_init_tile_shader(ScreenPtr screen); + #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c new file mode 100644 index 000000000..d47644297 --- /dev/null +++ b/glamor/glamor_tile.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_tile.c + * + * Implements the basic fill-with-a-tile support used by multiple GC ops. + */ + +void +glamor_init_tile_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + const char *tile_vs = + "uniform float x_bias;\n" + "uniform float x_scale;\n" + "uniform float y_bias;\n" + "uniform float y_scale;\n" + "void main()\n" + "{\n" + " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" + " (gl_Vertex.y + y_bias) * y_scale,\n" + " 0,\n" + " 1);\n" + " gl_TexCoord[0] = vec4(gl_MultiTexCoord0.xy, 0, 1);\n" + "}\n"; + const char *tile_fs = + "uniform sampler2D sampler;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" + "}\n"; + GLint fs_prog, vs_prog; + GLint sampler_uniform_location; + + if (!GLEW_ARB_fragment_shader) + return; + + glamor_priv->tile_prog = glCreateProgramObjectARB(); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, tile_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, tile_fs); + glAttachObjectARB(glamor_priv->tile_prog, vs_prog); + glAttachObjectARB(glamor_priv->tile_prog, fs_prog); + glamor_link_glsl_prog(glamor_priv->tile_prog); + + sampler_uniform_location = + glGetUniformLocationARB(glamor_priv->tile_prog, "sampler"); + glUseProgramObjectARB(glamor_priv->tile_prog); + glUniform1iARB(sampler_uniform_location, 0); + glamor_get_transform_uniform_locations(glamor_priv->tile_prog, + &glamor_priv->tile_transform); +} + +void +glamor_tile(PixmapPtr pixmap, PixmapPtr tile, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + int tile_x, int tile_y) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + int x1 = x; + int x2 = x + width; + int y1 = y; + int y2 = y + height; + int tile_x1 = tile_x + tile->screen_x; + int tile_x2 = tile_x + tile->screen_x + width; + int tile_y1 = tile_y + tile->screen_y; + int tile_y2 = tile_y + tile->screen_y + height; + glamor_pixmap_private *tile_priv = glamor_get_pixmap_private(tile); + + if (glamor_priv->tile_prog == 0) { + ErrorF("Tiling unsupported\n"); + goto fail; + } + + if (!glamor_set_destination_pixmap(pixmap)) + goto fail; + if (tile_priv->fb == 0) { + ErrorF("Non-FBO tile pixmap\n"); + goto fail; + } + if (alu != GXcopy) { + ErrorF("tile alu\n"); + goto fail; + } + if (!glamor_pm_is_solid(&pixmap->drawable, planemask)) { + ErrorF("tile pm\n"); + goto fail; + } + + glUseProgramObjectARB(glamor_priv->tile_prog); + glamor_set_transform_for_pixmap(pixmap, &glamor_priv->tile_transform); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tile_priv->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); + + tile_x += tile->screen_x; + tile_y += tile->screen_y; + + glBegin(GL_TRIANGLE_FAN); + glMultiTexCoord2f(0, tile_x1, tile_y1); + glVertex2f(x1, y1); + glMultiTexCoord2f(0, tile_x1, tile_y2); + glVertex2f(x1, y2); + glMultiTexCoord2f(0, tile_x2, tile_y2); + glVertex2f(x2, y2); + glMultiTexCoord2f(0, tile_x2, tile_y1); + glVertex2f(x2, y1); + glEnd(); + + glUseProgramObjectARB(0); + glDisable(GL_TEXTURE_2D); + return; + +fail: + glamor_solid_fail_region(pixmap, x, y, width, height); + return; +} From 2fa26c4958168064da95361db78ccc518c8f3ed8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 16:43:03 -0700 Subject: [PATCH 022/462] glamor: Free resources when destroying pixmaps. --- glamor/glamor.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index c3e4eb9f8..03886ad65 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -121,6 +121,13 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, 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); + } + return fbDestroyPixmap(pixmap); } From f6cffbb2ba66948ad5cc1cbe20e12de204de175d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 16:43:22 -0700 Subject: [PATCH 023/462] glamor: Add stub Composite support. --- glamor/Makefile.am | 1 + glamor/glamor.c | 14 ++++++++++++++ glamor/glamor_priv.h | 15 +++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 2453566fc..3f5a2002b 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -19,5 +19,6 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ + glamor_render.c \ glamor_tile.c \ glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 03886ad65..ff31f5dba 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -147,6 +147,9 @@ Bool glamor_init(ScreenPtr screen) { glamor_screen_private *glamor_priv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(screen); +#endif glamor_priv = xcalloc(1, sizeof(*glamor_priv)); if (glamor_priv == NULL) @@ -193,6 +196,11 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_get_spans = screen->GetSpans; screen->GetSpans = glamor_get_spans; +#ifdef RENDER + glamor_priv->saved_composite = ps->Composite; + ps->Composite = glamor_composite; +#endif + glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); @@ -208,9 +216,15 @@ void glamor_fini(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(screen); +#endif screen->CreateGC = glamor_priv->saved_create_gc; screen->CreatePixmap = glamor_priv->saved_create_pixmap; screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; screen->GetSpans = glamor_priv->saved_get_spans; +#ifdef RENDER + ps->Composite = glamor_priv->saved_composite; +#endif } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 9bae8144b..aee8e2d3e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -43,6 +43,7 @@ typedef struct glamor_screen_private { CreatePixmapProcPtr saved_create_pixmap; DestroyPixmapProcPtr saved_destroy_pixmap; GetSpansProcPtr saved_get_spans; + CompositeProcPtr saved_composite; /* glamor_solid */ GLint solid_prog; @@ -135,6 +136,20 @@ glamor_get_spans(DrawablePtr drawable, int nspans, char *dst_start); +/* glamor_render.c */ +void glamor_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + /* glamor_tile.c */ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, From 7500ee2b0215932ecb6688f301fb4e6f080f8a66 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 17:05:00 -0700 Subject: [PATCH 024/462] glamor: Fill in 1 and 24-bit getspans. --- glamor/glamor_getspans.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 8466208d7..5853f9450 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -31,6 +31,18 @@ #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, @@ -41,10 +53,20 @@ glamor_get_spans(DrawablePtr drawable, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - int i; + int i, j; + uint8_t *temp_dst = NULL, *readpixels_dst = (uint8_t *)dst; switch (drawable->depth) { + case 1: + temp_dst = xalloc(4 * wmax); + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; + readpixels_dst = temp_dst; + 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; @@ -65,7 +87,14 @@ glamor_get_spans(DrawablePtr drawable, widths[i], 1, format, type, - dst); - dst += PixmapBytePad(widths[i], drawable->depth); + 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); + } } } From 60ca0260f23cac6577aa85aacb0e5644d5f1b349 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 20 Aug 2009 17:17:43 -0700 Subject: [PATCH 025/462] glamor: Add more solid_fail_regions for software fallbacks. --- glamor/glamor_core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 549a5f313..5ecc894bb 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -195,14 +195,18 @@ glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, unsigned long fg_pixel, unsigned long bg_pixel, int stipple_x, int stipple_y) { - ErrorF("stubbed out stipple\n"); + ErrorF("stubbed out stipple depth %d\n", pixmap->drawable.depth); + glamor_solid_fail_region(pixmap, x, y, width, height); } static void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { - ErrorF("stub put_image\n"); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + + ErrorF("stub put_image depth %d\n", drawable->depth); + glamor_solid_fail_region(pixmap, x, y, w, h); } static void @@ -253,7 +257,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0 || gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { - ErrorF("stub poly_line\n"); + ErrorF("stub poly_line depth %d\n", drawable->depth); return; } @@ -271,8 +275,12 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, } if (x1 != x2 && y1 != y2) { + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + xfree(rects); - ErrorF("stub poly_line\n"); + + ErrorF("stub diagonal poly_line\n"); + glamor_solid_fail_region(pixmap, x1, y1, x2 - x1, y2 - y1); return; } From 93ad09144213fe6b9ce8bea7ebfcc2d60887810b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 21 Aug 2009 10:02:02 -0700 Subject: [PATCH 026/462] glamor: Add trapezoids code. This fixes segfaults on starting gnome-terminal. --- glamor/glamor.c | 2 ++ glamor/glamor_priv.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index ff31f5dba..05e05511b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -199,6 +199,8 @@ glamor_init(ScreenPtr screen) #ifdef RENDER glamor_priv->saved_composite = ps->Composite; ps->Composite = glamor_composite; + glamor_priv->saved_trapezoids = ps->Trapezoids; + ps->Trapezoids = glamor_trapezoids; #endif glamor_init_solid_shader(screen); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index aee8e2d3e..e8f486f27 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -44,6 +44,7 @@ typedef struct glamor_screen_private { DestroyPixmapProcPtr saved_destroy_pixmap; GetSpansProcPtr saved_get_spans; CompositeProcPtr saved_composite; + TrapezoidsProcPtr saved_trapezoids; /* glamor_solid */ GLint solid_prog; @@ -149,6 +150,10 @@ void glamor_composite(CARD8 op, INT16 yDst, CARD16 width, CARD16 height); +void glamor_trapezoids(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid *traps); /* glamor_tile.c */ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, From f66e5c4145d003247447ac1bf93f9737c6eaa27c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 21 Aug 2009 10:05:32 -0700 Subject: [PATCH 027/462] glamor: Add 8bpp to get/setspans. --- glamor/glamor_core.c | 3 +++ glamor/glamor_getspans.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 5ecc894bb..ed6663e5c 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -218,6 +218,9 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, int i; switch (drawable->depth) { + case 8: + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; case 24: case 32: format = GL_BGRA; diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 5853f9450..9a7066cb9 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -63,6 +63,9 @@ glamor_get_spans(DrawablePtr drawable, type = GL_UNSIGNED_BYTE; readpixels_dst = temp_dst; break; + case 8: + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; case 24: format = GL_RGB; type = GL_UNSIGNED_BYTE; From 2b657d91d80a0a4d9fa2e390255ff87f51426b7c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 22 Aug 2009 15:54:24 -0700 Subject: [PATCH 028/462] glamor: Add untested putimage support. --- glamor/Makefile.am | 1 + glamor/glamor_core.c | 10 --- glamor/glamor_priv.h | 5 ++ glamor/glamor_putimage.c | 129 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 glamor/glamor_putimage.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 3f5a2002b..43512f720 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -19,6 +19,7 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ + glamor_putimage.c \ glamor_render.c \ glamor_tile.c \ glamor.h diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index ed6663e5c..ba73c0bd2 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -199,16 +199,6 @@ glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, glamor_solid_fail_region(pixmap, x, y, width, height); } -static void -glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, - int w, int h, int leftPad, int format, char *bits) -{ - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - - ErrorF("stub put_image depth %d\n", drawable->depth); - glamor_solid_fail_region(pixmap, x, y, w, h); -} - static void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index e8f486f27..74c1aea68 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -137,6 +137,11 @@ glamor_get_spans(DrawablePtr drawable, int nspans, char *dst_start); +/* glamor_putimage.c */ +void +glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, + int w, int h, int leftPad, int format, char *bits); + /* glamor_render.c */ void glamor_composite(CARD8 op, PicturePtr pSrc, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c new file mode 100644 index 000000000..2795d837e --- /dev/null +++ b/glamor/glamor_putimage.c @@ -0,0 +1,129 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + + +/** @file glamor_putaimge.c + * + * XPutImage implementation + */ +#include "glamor_priv.h" + +void +glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, + int w, int h, int left_pad, int image_format, char *bits) +{ + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + GLenum type, format; + RegionPtr clip; + BoxPtr pbox; + int nbox; + int bpp = drawable->bitsPerPixel; + int src_stride = PixmapBytePad(w, drawable->depth); + + if (gc->alu != GXcopy) { + ErrorF("putimage: non-copy alu\n"); + goto fail; + } + if (!glamor_pm_is_solid(drawable, gc->planemask)) { + ErrorF("putimage: non-solid planemask\n"); + goto fail; + } + if (image_format != ZPixmap) { + ErrorF("putimage: non-ZPixmap\n"); + goto fail; + } + if (bpp < 8) { + ErrorF("putimage: bad bpp: %d\n", bpp); + return; + } + + switch (drawable->depth) { + 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: + ErrorF("stub put_image depth %d\n", drawable->depth); + goto fail; + break; + } + + if (!glamor_set_destination_pixmap(pixmap)) { + fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, + image_format, bits); + goto fail; + } + + x += drawable->x; + y += drawable->y; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride / (bpp / 8)); + clip = fbGetCompositeClip(gc); + for (nbox = REGION_NUM_RECTS(clip), + pbox = REGION_RECTS(clip); + nbox--; + pbox++) + { + int x1 = x; + int y1 = y; + int x2 = x + w; + int y2 = y + h; + char *src; + + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + + src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); + glRasterPos2i(x1 + pixmap->screen_x, y1 + pixmap->screen_y); + glDrawPixels(x2 - x1, + y2 - y1, + format, type, + src); + } + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + return; + +fail: + glamor_solid_fail_region(pixmap, x, y, w, h); +} From e3c02c09c125bb5def1a70a1264ef34b18182afa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 07:00:32 -0700 Subject: [PATCH 029/462] glamor: Add ALU support to solid, tile, and putimage. --- glamor/glamor_core.c | 61 ++++++++++++++++++++++++++++++++++++++++ glamor/glamor_fill.c | 2 ++ glamor/glamor_priv.h | 1 + glamor/glamor_putimage.c | 15 +++++----- glamor/glamor_tile.c | 6 ++-- 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index ba73c0bd2..055df399a 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -68,6 +68,67 @@ glamor_set_destination_pixmap(PixmapPtr pixmap) return TRUE; } +void +glamor_set_alu(unsigned char alu) +{ + if (alu == GXcopy) { + glDisable(GL_LOGIC_OP); + return; + } + + glEnable(GL_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) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 11d5f9841..f387dab62 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -153,6 +153,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, if (!glamor_set_destination_pixmap(pixmap)) return; + glamor_set_alu(alu); glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); @@ -167,6 +168,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glEnd(); glUseProgramObjectARB(0); + glamor_set_alu(GXcopy); } /* Highlight places where we're doing it wrong. */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 74c1aea68..6484c9495 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -100,6 +100,7 @@ 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); +void glamor_set_alu(unsigned char alu); void glamor_get_transform_uniform_locations(GLint prog, glamor_transform_uniforms *uniform_locations); void glamor_set_transform_for_pixmap(PixmapPtr pixmap, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 2795d837e..f1a4e947a 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -44,10 +44,12 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int bpp = drawable->bitsPerPixel; int src_stride = PixmapBytePad(w, drawable->depth); - if (gc->alu != GXcopy) { - ErrorF("putimage: non-copy alu\n"); - goto fail; + if (!glamor_set_destination_pixmap(pixmap)) { + fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, + image_format, bits); + return; } + if (!glamor_pm_is_solid(drawable, gc->planemask)) { ErrorF("putimage: non-solid planemask\n"); goto fail; @@ -80,11 +82,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, break; } - if (!glamor_set_destination_pixmap(pixmap)) { - fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, - image_format, bits); - goto fail; - } + glamor_set_alu(gc->alu); x += drawable->x; y += drawable->y; @@ -122,6 +120,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, src); } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glamor_set_alu(GXcopy); return; fail: diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index d47644297..c33b3c1a6 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -109,15 +109,12 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, ErrorF("Non-FBO tile pixmap\n"); goto fail; } - if (alu != GXcopy) { - ErrorF("tile alu\n"); - goto fail; - } if (!glamor_pm_is_solid(&pixmap->drawable, planemask)) { ErrorF("tile pm\n"); goto fail; } + glamor_set_alu(alu); glUseProgramObjectARB(glamor_priv->tile_prog); glamor_set_transform_for_pixmap(pixmap, &glamor_priv->tile_transform); @@ -143,6 +140,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glUseProgramObjectARB(0); glDisable(GL_TEXTURE_2D); + glamor_set_alu(GXcopy); return; fail: From cfb8dea815086b9aafd27bd314e02739e04dfc7d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 07:22:14 -0700 Subject: [PATCH 030/462] glamor: Hook up miGetImage to fix some invalid accesses. --- glamor/glamor.c | 3 +++ glamor/glamor_priv.h | 1 + 2 files changed, 4 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 05e05511b..a03274a54 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -196,6 +196,9 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_get_spans = screen->GetSpans; screen->GetSpans = glamor_get_spans; + glamor_priv->saved_get_image = screen->GetImage; + screen->GetImage = miGetImage; + #ifdef RENDER glamor_priv->saved_composite = ps->Composite; ps->Composite = glamor_composite; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 6484c9495..5d47c2590 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -43,6 +43,7 @@ typedef struct glamor_screen_private { CreatePixmapProcPtr saved_create_pixmap; DestroyPixmapProcPtr saved_destroy_pixmap; GetSpansProcPtr saved_get_spans; + GetImageProcPtr saved_get_image; CompositeProcPtr saved_composite; TrapezoidsProcPtr saved_trapezoids; From cdb1fe6d9682616b1def52fa38b2dae623e2503f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 08:03:17 -0700 Subject: [PATCH 031/462] glamor: Move setspans to a separate file. --- glamor/Makefile.am | 1 + glamor/glamor_core.c | 35 --------------------- glamor/glamor_priv.h | 4 +++ glamor/glamor_setspans.c | 67 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 glamor/glamor_setspans.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 43512f720..098aa37c0 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -20,6 +20,7 @@ libglamor_la_SOURCES = \ glamor_fillspans.c \ glamor_getspans.c \ glamor_putimage.c \ + glamor_setspans.c \ glamor_render.c \ glamor_tile.c \ glamor.h diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 055df399a..38829de99 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -260,41 +260,6 @@ glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, glamor_solid_fail_region(pixmap, x, y, width, height); } -static void -glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted) -{ - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - GLenum format, type; - int i; - - switch (drawable->depth) { - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - case 24: - case 32: - format = GL_BGRA; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - default: - ErrorF("Unknown setspans depth %d\n", drawable->depth); - return; - } - - if (!glamor_set_destination_pixmap(dest_pixmap)) - return; - for (i = 0; i < n; i++) { - glRasterPos2i(points[i].x - dest_pixmap->screen_x, - points[i].y - dest_pixmap->screen_y); - glDrawPixels(widths[i], - 1, - format, type, - src); - src += PixmapBytePad(widths[i], drawable->depth); - } -} - /** * glamor_poly_lines() checks if it can accelerate the lines as a group of * horizontal or vertical lines (rectangles), and uses existing rectangle fill diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 5d47c2590..3929819e8 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -139,6 +139,10 @@ glamor_get_spans(DrawablePtr drawable, int nspans, char *dst_start); +/* glamor_setspans.c */ +void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int n, int sorted); + /* glamor_putimage.c */ void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c new file mode 100644 index 000000000..bf9c50818 --- /dev/null +++ b/glamor/glamor_setspans.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int n, int sorted) +{ + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + GLenum format, type; + int i; + + switch (drawable->depth) { + case 8: + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; + case 24: + case 32: + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + default: + ErrorF("Unknown setspans depth %d\n", drawable->depth); + return; + } + + if (!glamor_set_destination_pixmap(dest_pixmap)) + return; + for (i = 0; i < n; i++) { + glRasterPos2i(points[i].x - dest_pixmap->screen_x, + points[i].y - dest_pixmap->screen_y); + glDrawPixels(widths[i], + 1, + format, type, + src); + src += PixmapBytePad(widths[i], drawable->depth); + } +} From 0360ba361a67f6cfa5c9c65590ed8440a153c16e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 08:06:57 -0700 Subject: [PATCH 032/462] glamor: Fix memory leak in getspans. --- glamor/glamor_getspans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 9a7066cb9..21ba9f095 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -58,7 +58,7 @@ glamor_get_spans(DrawablePtr drawable, switch (drawable->depth) { case 1: - temp_dst = xalloc(4 * wmax); + temp_dst = xalloc(wmax); format = GL_ALPHA; type = GL_UNSIGNED_BYTE; readpixels_dst = temp_dst; @@ -100,4 +100,5 @@ glamor_get_spans(DrawablePtr drawable, readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } } + xfree(temp_dst); } From d9eef95c74b7b04a3398b4cfc1a81b480838b25e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 08:17:06 -0700 Subject: [PATCH 033/462] glamor: Fix bad fallthrough in getspans (accessing invalid memory). --- glamor/glamor_getspans.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 21ba9f095..76c6cceef 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -66,6 +66,7 @@ glamor_get_spans(DrawablePtr drawable, case 8: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; + break; case 24: format = GL_RGB; type = GL_UNSIGNED_BYTE; From c70ce72fd74354a0b9731dc8d4451f6aaf951117 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 08:24:54 -0700 Subject: [PATCH 034/462] glamor: Give setspans the same format support as getspans. --- glamor/glamor_setspans.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index bf9c50818..48168a937 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -37,13 +37,30 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - int i; + uint8_t *temp_src = NULL, *drawpixels_src = (uint8_t *)src; + int i, j; + int wmax = 0; + + for (i = 0 ; i < n; i++) { + if (wmax < widths[i]) + wmax = widths[i]; + } switch (drawable->depth) { + case 1: + temp_src = xalloc(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; @@ -56,12 +73,26 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (!glamor_set_destination_pixmap(dest_pixmap)) return; 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; + } + } + glRasterPos2i(points[i].x - dest_pixmap->screen_x, points[i].y - dest_pixmap->screen_y); glDrawPixels(widths[i], 1, format, type, - src); - src += PixmapBytePad(widths[i], drawable->depth); + drawpixels_src); + if (temp_src) { + src += PixmapBytePad(widths[i], drawable->depth); + } else { + drawpixels_src += PixmapBytePad(widths[i], drawable->depth); + } } + xfree(temp_src); } From 882411bef1091f97f61ae27a549970d87eef9cab Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 08:29:30 -0700 Subject: [PATCH 035/462] glamor: add alu support to setspans. --- glamor/glamor_setspans.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 48168a937..f81551ad0 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -72,6 +72,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (!glamor_set_destination_pixmap(dest_pixmap)) return; + glamor_set_alu(gc->alu); for (i = 0; i < n; i++) { if (temp_src) { for (j = 0; j < widths[i]; j++) { @@ -94,5 +95,6 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } } + glamor_set_alu(GXcopy); xfree(temp_src); } From 44e4599b83cc330a7c9edd7e18266f222a69418a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 08:59:52 -0700 Subject: [PATCH 036/462] glamor: Move planemask to a function in case I decide to fill it in. --- glamor/glamor_core.c | 11 +++++++++++ glamor/glamor_fill.c | 3 +++ glamor/glamor_priv.h | 1 + glamor/glamor_putimage.c | 8 ++++---- glamor/glamor_setspans.c | 8 +++++++- glamor/glamor_tile.c | 6 ++---- 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 38829de99..58cb35716 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -68,6 +68,17 @@ glamor_set_destination_pixmap(PixmapPtr pixmap) 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) { diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index f387dab62..6290f1210 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -154,6 +154,8 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, if (!glamor_set_destination_pixmap(pixmap)) return; glamor_set_alu(alu); + if (!glamor_set_planemask(pixmap, planemask)) + goto fail; glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); @@ -168,6 +170,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glEnd(); glUseProgramObjectARB(0); +fail: glamor_set_alu(GXcopy); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3929819e8..d054372b4 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -102,6 +102,7 @@ void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, GLfloat *color); Bool glamor_set_destination_pixmap(PixmapPtr pixmap); void glamor_set_alu(unsigned char alu); +Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); void glamor_get_transform_uniform_locations(GLint prog, glamor_transform_uniforms *uniform_locations); void glamor_set_transform_for_pixmap(PixmapPtr pixmap, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index f1a4e947a..36f5c85d7 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -50,17 +50,15 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, return; } - if (!glamor_pm_is_solid(drawable, gc->planemask)) { - ErrorF("putimage: non-solid planemask\n"); + if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; - } if (image_format != ZPixmap) { ErrorF("putimage: non-ZPixmap\n"); goto fail; } if (bpp < 8) { ErrorF("putimage: bad bpp: %d\n", bpp); - return; + goto fail; } switch (drawable->depth) { @@ -121,8 +119,10 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); return; fail: + glamor_set_planemask(pixmap, ~0); glamor_solid_fail_region(pixmap, x, y, w, h); } diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index f81551ad0..65471e916 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -71,8 +71,12 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, } if (!glamor_set_destination_pixmap(dest_pixmap)) - return; + goto fail; + if (!glamor_set_planemask(dest_pixmap, gc->planemask)) + goto fail; glamor_set_alu(gc->alu); + if (!glamor_set_planemask(dest_pixmap, gc->planemask)) + goto fail; for (i = 0; i < n; i++) { if (temp_src) { for (j = 0; j < widths[i]; j++) { @@ -95,6 +99,8 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } } +fail: + glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(GXcopy); xfree(temp_src); } diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index c33b3c1a6..cb1fe2d68 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -109,11 +109,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, ErrorF("Non-FBO tile pixmap\n"); goto fail; } - if (!glamor_pm_is_solid(&pixmap->drawable, planemask)) { - ErrorF("tile pm\n"); + if (!glamor_set_planemask(pixmap, planemask)) goto fail; - } - glamor_set_alu(alu); glUseProgramObjectARB(glamor_priv->tile_prog); glamor_set_transform_for_pixmap(pixmap, &glamor_priv->tile_transform); @@ -141,6 +138,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glUseProgramObjectARB(0); glDisable(GL_TEXTURE_2D); glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); return; fail: From 5fadea5d9c02670c35ddf3e0f12f9d355b412103 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 09:10:14 -0700 Subject: [PATCH 037/462] glamor: Fix some screen_xy offsets to be the right way around. --- glamor/glamor_putimage.c | 2 +- glamor/glamor_tile.c | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 36f5c85d7..a0b8635dd 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -111,7 +111,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, continue; src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); - glRasterPos2i(x1 + pixmap->screen_x, y1 + pixmap->screen_y); + glRasterPos2i(x1 - pixmap->screen_x, y1 - pixmap->screen_y); glDrawPixels(x2 - x1, y2 - y1, format, type, diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index cb1fe2d68..517dbd3ea 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -92,10 +92,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x2 = x + width; int y1 = y; int y2 = y + height; - int tile_x1 = tile_x + tile->screen_x; - int tile_x2 = tile_x + tile->screen_x + width; - int tile_y1 = tile_y + tile->screen_y; - int tile_y2 = tile_y + tile->screen_y + height; + int tile_x1 = tile_x - tile->screen_x; + int tile_x2 = tile_x - tile->screen_x + width; + int tile_y1 = tile_y - tile->screen_y; + int tile_y2 = tile_y - tile->screen_y + height; glamor_pixmap_private *tile_priv = glamor_get_pixmap_private(tile); if (glamor_priv->tile_prog == 0) { @@ -121,9 +121,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); - tile_x += tile->screen_x; - tile_y += tile->screen_y; - glBegin(GL_TRIANGLE_FAN); glMultiTexCoord2f(0, tile_x1, tile_y1); glVertex2f(x1, y1); From 4a51cc0440c8d026fd8c82b40cfb188c6ea4a9f0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 24 Aug 2009 09:14:20 -0700 Subject: [PATCH 038/462] glamor: Add clipping to setspans. --- glamor/glamor_setspans.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 65471e916..66ec3dafd 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -40,6 +40,8 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, uint8_t *temp_src = NULL, *drawpixels_src = (uint8_t *)src; int i, j; int wmax = 0; + RegionPtr clip = fbGetCompositeClip(gc); + BoxRec *pbox; for (i = 0 ; i < n; i++) { if (wmax < widths[i]) @@ -87,12 +89,23 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, } } - glRasterPos2i(points[i].x - dest_pixmap->screen_x, - points[i].y - dest_pixmap->screen_y); - glDrawPixels(widths[i], - 1, - format, type, - drawpixels_src); + n = REGION_NUM_RECTS(clip); + pbox = REGION_RECTS(clip); + while (n--) { + if (pbox->y1 > points[i].y) + break; + glScissor(pbox->x1, + points[i].y - dest_pixmap->screen_y, + pbox->x2 - pbox->x1, + 1); + glEnable(GL_SCISSOR_TEST); + glRasterPos2i(points[i].x - dest_pixmap->screen_x, + points[i].y - dest_pixmap->screen_y); + glDrawPixels(widths[i], + 1, + format, type, + drawpixels_src); + } if (temp_src) { src += PixmapBytePad(widths[i], drawable->depth); } else { @@ -100,6 +113,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, } } fail: + glDisable(GL_SCISSOR_TEST); glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(GXcopy); xfree(temp_src); From aa133069745fc59bb2f212b0816add9bae40c376 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 25 Aug 2009 12:10:32 -0700 Subject: [PATCH 039/462] glamor: Start adding render acceleration support. This brings in idr's glu3 code. We'll probably want to move to linking to it as a library, once an ABI-stable release is out. --- configure.ac | 1 + glamor/Makefile.am | 4 + glamor/glamor.c | 1 + glamor/glamor_priv.h | 16 + glamor/glamor_render.c | 620 ++++++++++++++++++++++++++++++++++++++ glamor/glu3/Makefile.am | 15 + glamor/glu3/glu3.h | 192 ++++++++++++ glamor/glu3/glu3_scalar.h | 388 ++++++++++++++++++++++++ glamor/glu3/matrix.c | 217 +++++++++++++ 9 files changed, 1454 insertions(+) create mode 100644 glamor/glamor_render.c create mode 100644 glamor/glu3/Makefile.am create mode 100644 glamor/glu3/glu3.h create mode 100644 glamor/glu3/glu3_scalar.h create mode 100644 glamor/glu3/matrix.c diff --git a/configure.ac b/configure.ac index 3954ecc06..7a8e507e7 100644 --- a/configure.ac +++ b/configure.ac @@ -2147,6 +2147,7 @@ Xi/Makefile xfixes/Makefile exa/Makefile glamor/Makefile +glamor/glu3/Makefile hw/Makefile hw/xfree86/Makefile hw/xfree86/common/Makefile diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 098aa37c0..4d307fe7a 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -4,6 +4,8 @@ noinst_LTLIBRARIES = libglamor.la # built (in hw/xfree86/os-support/solaris) until after glamor is built SOLARIS_ASM_CFLAGS="" +SUBDIRS = glu3 + if XORG sdk_HEADERS = glamor.h endif @@ -24,3 +26,5 @@ libglamor_la_SOURCES = \ glamor_render.c \ glamor_tile.c \ glamor.h +libglamor_la_LIBADD = \ + glu3/libglu3.la diff --git a/glamor/glamor.c b/glamor/glamor.c index a03274a54..43e1c7d3a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -208,6 +208,7 @@ glamor_init(ScreenPtr screen) glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); + glamor_init_composite_shaders(screen); return TRUE; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index d054372b4..864be51ab 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -38,6 +38,13 @@ typedef struct glamor_transform_uniforms { 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; +} glamor_composite_shader; + typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; @@ -52,8 +59,12 @@ typedef struct glamor_screen_private { GLint solid_color_uniform_location; glamor_transform_uniforms solid_transform; + /* glamor_tile */ GLint tile_prog; glamor_transform_uniforms tile_transform; + + /* glamor_composite */ + glamor_composite_shader composite_shader[2]; } glamor_screen_private; typedef struct glamor_pixmap_private { @@ -75,6 +86,10 @@ glamor_get_pixmap_private(PixmapPtr pixmap) 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)) + /** * Returns TRUE if the given planemask covers all the significant bits in the * pixel values for pDrawable. @@ -166,6 +181,7 @@ void glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid *traps); +void glamor_init_composite_shaders(ScreenPtr screen); /* glamor_tile.c */ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c new file mode 100644 index 000000000..d0c955792 --- /dev/null +++ b/glamor/glamor_render.c @@ -0,0 +1,620 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + + +/** @file glamor_render.c + * + * Render acceleration implementation + */ + +#include "glamor_priv.h" + +#ifdef RENDER +#include "mipict.h" + +#include "glu3/glu3.h" + +struct shader_key { + Bool has_mask; +}; + +struct blendinfo { + 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}, +}; + +#define HAS_MASK_INDEX 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); + int index = 0; + + if (key->has_mask) + index += HAS_MASK_INDEX; + + assert(index < ARRAY_SIZE(glamor_priv->composite_shader)); + + return &glamor_priv->composite_shader[index]; +} + +static GLuint +glamor_create_composite_fs(struct shader_key *key) +{ + const char *header = + "uniform sampler2D source_sampler;\n" + "varying vec4 source_coords;\n"; + const char *mask_header = + "uniform sampler2D mask_sampler;\n" + "varying vec4 mask_coords;\n"; + const char *main_opening = + "void main()\n" + "{\n" + " vec4 result;\n" + " result = texture2DProj(source_sampler, source_coords.xyw);\n"; + const char *source_in_mask = + " vec4 mask = texture2DProj(mask_sampler, mask_coords.xyw);\n" + " result = result * mask.w;\n"; + const char *main_closing = + " gl_FragColor = result;\n" + "}\n"; + char *source; + GLuint prog; + + source = XNFprintf("%s%s%s%s%s", + header, + key->has_mask ? mask_header : "", + main_opening, + key->has_mask ? source_in_mask : "", + main_closing); + + prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); + xfree(source); + + return prog; +} + +static GLuint +glamor_create_composite_vs(struct shader_key *key) +{ + const char *header = + "uniform mat4 dest_to_dest;\n" + "uniform mat4 dest_to_source;\n" + "varying vec4 source_coords;\n"; + const char *mask_header = + "uniform mat4 dest_to_mask;\n" + "varying vec4 mask_coords;\n"; + const char *main_opening = + "void main()\n" + "{\n" + " vec4 incoming_dest_coords = vec4(gl_Vertex.xy, 0, 1);\n" + " gl_Position = dest_to_dest * incoming_dest_coords;\n" + " source_coords = dest_to_source * incoming_dest_coords;\n"; + const char *mask_coords = + " mask_coords = dest_to_mask * incoming_dest_coords;\n"; + const char *main_closing = + "}\n"; + char *source; + GLuint prog; + + source = XNFprintf("%s%s%s%s%s", + header, + key->has_mask ? mask_header : "", + main_opening, + key->has_mask ? mask_coords : "", + main_closing); + + prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); + xfree(source); + + return prog; +} + +static void +glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) +{ + GLuint vs, fs, prog; + GLint source_sampler_uniform_location, mask_sampler_uniform_location; + glamor_composite_shader *shader; + + shader = glamor_lookup_composite_shader(screen, key); + + 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); + + shader->prog = prog; + + glUseProgramObjectARB(prog); + source_sampler_uniform_location = glGetUniformLocationARB(prog, + "source_sampler"); + shader->dest_to_dest_uniform_location = + glGetUniformLocationARB(prog, "dest_to_dest"); + shader->dest_to_source_uniform_location = + glGetUniformLocationARB(prog, "dest_to_source"); + glUniform1i(source_sampler_uniform_location, 0); + + if (key->has_mask) { + mask_sampler_uniform_location = glGetUniformLocationARB(prog, + "mask_sampler"); + glUniform1i(mask_sampler_uniform_location, 1); + shader->dest_to_mask_uniform_location = + glGetUniformLocationARB(prog, "dest_to_mask"); + } +} + +void +glamor_init_composite_shaders(ScreenPtr screen) +{ + struct shader_key key; + + key.has_mask = FALSE; + glamor_create_composite_shader(screen, &key); + key.has_mask = TRUE; + glamor_create_composite_shader(screen, &key); +} + +static void +glamor_set_composite_transform_matrix(GLUmat4 *m, + PicturePtr picture, + float x_source, + float y_source) +{ + GLUmat4 temp; + DrawablePtr drawable = picture->pDrawable; + GLUvec4 scale = {{1.0f / drawable->width, + 1.0f / drawable->height, + 1.0, + 1.0}}; + + gluTranslate3f(m, -x_source, -y_source, 0.0); + gluScale4v(&temp, &scale); + gluMult4m_4m(m, &temp, m); +} + +static Bool +glamor_set_composite_op(ScreenPtr screen, + CARD8 op, PicturePtr dest, PicturePtr mask) +{ + GLenum source_blend, dest_blend; + struct blendinfo *op_info; + + if (op >= ARRAY_SIZE(composite_op_info)) { + ErrorF("unsupported render op\n"); + return GL_FALSE; + } + op_info = &composite_op_info[op]; + + source_blend = op_info->source_blend; + dest_blend = op_info->dest_blend; + + if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) != 0 && + op_info->source_alpha && source_blend != GL_ZERO) { + } + + /* 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; +} + +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; + } + + 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); +} + +void +glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, + INT16 y_dest, + CARD16 width, + CARD16 height) +{ + ScreenPtr screen = dest->pDrawable->pScreen; + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap, mask_pixmap = NULL; + glamor_pixmap_private *source_pixmap_priv, *mask_pixmap_priv = NULL; + struct shader_key key; + glamor_composite_shader *shader; + GLUmat4 dest_to_dest, dest_to_source, dest_to_mask; + RegionRec region; + int i; + + /* Do two-pass PictOpOver componentAlpha, until we enable + * dual source color blending. + */ + if (mask && mask->componentAlpha && 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; + } + + key.has_mask = (mask != NULL); + if (!source->pDrawable) { + ErrorF("source-only source\n"); + goto fail; + } + if (mask && !mask->pDrawable) { + ErrorF("source-only mask\n"); + goto fail; + } + if (source->alphaMap) { + ErrorF("source alphaMap\n"); + goto fail; + } + if (mask && mask->alphaMap) { + ErrorF("mask alphaMap\n"); + goto fail; + } + + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (source_pixmap == dest_pixmap) { + ErrorF("source == dest\n"); + goto fail; + } + if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { + ErrorF("no FBO in source\n"); + goto fail; + } + if (mask) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + if (mask_pixmap == dest_pixmap) { + ErrorF("mask == dest\n"); + goto fail; + } + if (!mask_pixmap_priv || mask_pixmap_priv->tex == 0) { + ErrorF("no FBO in mask\n"); + goto fail; + } + } + + shader = glamor_lookup_composite_shader(screen, &key); + if (shader->prog == 0) { + ErrorF("No program compiled for this render accel 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; + } + + 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; + } + + gluOrtho6f(&dest_to_dest, + dest_pixmap->screen_x, dest_pixmap->screen_x + width, + dest_pixmap->screen_y, dest_pixmap->screen_y + height, + -1, 1); + glUniformMatrix4fvARB(shader->dest_to_dest_uniform_location, 1, 0, + (float *)&dest_to_dest); + glamor_set_composite_transform_matrix(&dest_to_source, + source, + x_source - x_dest, + y_source - x_dest); + glUniformMatrix4fvARB(shader->dest_to_source_uniform_location, 1, 0, + (float *)&dest_to_source); + + if (mask) { + glamor_set_composite_transform_matrix(&dest_to_mask, + mask, + x_mask - x_dest, + y_mask - x_dest); + glUniformMatrix4fvARB(shader->dest_to_mask_uniform_location, 1, 0, + (float *)&dest_to_mask); + } + + glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); + if (mask) + glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); + + if (!miComputeCompositeRegion(®ion, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height)) + return; + + glBegin(GL_QUADS); + for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { + BoxPtr box = ®ION_RECTS(®ion)[i]; + glVertex2i(box->x1, box->y1); + glVertex2i(box->x2, box->y1); + glVertex2i(box->x2, box->y2); + glVertex2i(box->x1, box->y2); + } + glEnd(); + + glamor_set_composite_op(screen, PictOpSrc, dest, mask); + glUseProgramObjectARB(0); + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + + return; + +fail: + glamor_set_composite_op(screen, PictOpSrc, dest, mask); + glUseProgramObjectARB(0); + glamor_solid_fail_region(dest_pixmap, x_dest, y_dest, width, height); +} + + +/** + * Creates an appropriate picture to upload our alpha mask into (which + * we calculated in system memory) + */ +static PicturePtr +glamor_create_mask_picture(ScreenPtr screen, + PicturePtr dst, + PictFormatPtr pict_format, + CARD16 width, + CARD16 height) +{ + 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; + } + + 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; +} + +/** + * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid + * accumulation in system memory. + */ +void +glamor_trapezoids(CARD8 op, + PicturePtr src, PicturePtr dst, + 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; + } + + 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); +} + +#endif /* RENDER */ diff --git a/glamor/glu3/Makefile.am b/glamor/glu3/Makefile.am new file mode 100644 index 000000000..7d141a7fc --- /dev/null +++ b/glamor/glu3/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libglu3.la + +# Override these since glu3 doesn't need them and the needed files aren't +# built (in hw/xfree86/os-support/solaris) until after glu3 is built +SOLARIS_ASM_CFLAGS="" + +INCLUDES = \ + $(XORG_INCS) + +AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) + +libglu3_la_SOURCES = \ + matrix.c \ + glu3.h \ + glu3_scalar.h diff --git a/glamor/glu3/glu3.h b/glamor/glu3/glu3.h new file mode 100644 index 000000000..29dba380a --- /dev/null +++ b/glamor/glu3/glu3.h @@ -0,0 +1,192 @@ +/* + * Copyright © 2009 Ian D. Romanick + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __glu3_h__ +#define __glu3_h__ + +#include + +#define GLU_VERSION_3_0 + +struct GLUmat4; + +struct GLUvec4 { + GLfloat values[4]; + +#ifdef __cplusplus + inline GLUvec4(void) + { + } + + inline GLUvec4(GLfloat x , GLfloat y, GLfloat z, GLfloat w) + { + values[0] = x; + values[1] = y; + values[2] = z; + values[3] = w; + } + + inline GLUvec4(const GLUvec4 &v) + { + values[0] = v.values[0]; + values[1] = v.values[1]; + values[2] = v.values[2]; + values[3] = v.values[3]; + } + + GLUvec4 operator *(const GLUmat4 &) const; + GLUvec4 operator *(const GLUvec4 &) const; + GLUvec4 operator *(GLfloat) const; + + GLUvec4 operator +(const GLUvec4 &) const; + GLUvec4 operator -(const GLUvec4 &) const; +#endif /* __cplusplus */ +}; + + +struct GLUmat4 { + struct GLUvec4 col[4]; + +#ifdef __cplusplus + inline GLUmat4(void) + { + } + + inline GLUmat4(const GLUvec4 & c0, const GLUvec4 & c1, + const GLUvec4 & c2, const GLUvec4 & c3) + { + col[0] = c0; + col[1] = c1; + col[2] = c2; + col[3] = c3; + } + + inline GLUmat4(const GLUmat4 &m) + { + col[0] = m.col[0]; + col[1] = m.col[1]; + col[2] = m.col[2]; + col[3] = m.col[3]; + } + + + GLUvec4 operator *(const GLUvec4 &) const; + GLUmat4 operator *(const GLUmat4 &) const; + GLUmat4 operator *(GLfloat) const; + + GLUmat4 operator +(const GLUmat4 &) const; + GLUmat4 operator -(const GLUmat4 &) const; +#endif /* __cplusplus */ +}; + +#define GLU_MAX_STACK_DEPTH 32 + +struct GLUmat4Stack { + struct GLUmat4 stack[GLU_MAX_STACK_DEPTH]; + unsigned top; + +#ifdef __cplusplus + GLUmat4Stack() : top(0) + { + /* empty */ + } +#endif /* __cplusplus */ +}; + +#ifndef __cplusplus +typedef struct GLUvec4 GLUvec4; +typedef struct GLUmat4 GLUmat4; +typedef struct GLUmat4Stack GLUmat4Stack; +#endif /* __cplusplus */ + + +#ifdef __cplusplus +extern "C" { +#endif + +GLfloat gluDot4_4v(const GLUvec4 *, const GLUvec4 *); +GLfloat gluDot3_4v(const GLUvec4 *, const GLUvec4 *); +GLfloat gluDot2_4v(const GLUvec4 *, const GLUvec4 *); + +void gluCross4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); +void gluNormalize4v(GLUvec4 *result, const GLUvec4 *); +GLfloat gluLength4v(const GLUvec4 *); +GLfloat gluLengthSqr4v(const GLUvec4 *); +void gluOuter4v(GLUmat4 *result, const GLUvec4 *, const GLUvec4 *); + + +void gluMult4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); +void gluDiv4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); +void gluAdd4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); +void gluSub4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); + +void gluMult4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); +void gluDiv4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); +void gluAdd4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); +void gluSub4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); + +void gluMult4m_4m(GLUmat4 *result, const GLUmat4 *, const GLUmat4 *); +void gluAdd4m_4m(GLUmat4 *result, const GLUmat4 *, const GLUmat4 *); +void gluSub4m_4m(GLUmat4 *result, const GLUmat4 *, const GLUmat4 *); +void gluMult4m_4v(GLUvec4 *result, const GLUmat4 *m, const GLUvec4 *v); + +void gluMult4m_f(GLUmat4 *result, const GLUmat4 *, GLfloat); + +void gluScale4v(GLUmat4 *result, const GLUvec4 *); +void gluTranslate3f(GLUmat4 *result, GLfloat x, GLfloat y, GLfloat z); +void gluTranslate4v(GLUmat4 *result, const GLUvec4 *); +void gluRotate4v(GLUmat4 *result, const GLUvec4 *axis, GLfloat angle); +void gluLookAt4v(GLUmat4 *result, const GLUvec4 *eye, const GLUvec4 *center, + const GLUvec4 *up); +void gluPerspective4f(GLUmat4 *result, GLfloat fovy, GLfloat aspect, + GLfloat near, GLfloat far); +void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m); +void gluFrustum6f(GLUmat4 *result, + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far); +void gluOrtho6f(GLUmat4 *result, + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far); + +extern const GLUmat4 gluIdentityMatrix; + +#ifdef __cplusplus +}; +#endif + +#ifdef __cplusplus +GLfloat gluDot4(const GLUvec4 &, const GLUvec4 &); +GLfloat gluDot3(const GLUvec4 &, const GLUvec4 &); +GLfloat gluDot2(const GLUvec4 &, const GLUvec4 &); + +GLUvec4 gluCross(const GLUvec4 &, const GLUvec4 &); +GLUvec4 gluNormalize(const GLUvec4 &); +GLfloat gluLength(const GLUvec4 &); +GLfloat gluLengthSqr(const GLUvec4 &); +#endif /* __cplusplus */ + +#include "glu3_scalar.h" + +#endif /* __glu3_h__ */ diff --git a/glamor/glu3/glu3_scalar.h b/glamor/glu3/glu3_scalar.h new file mode 100644 index 000000000..3e87b8cce --- /dev/null +++ b/glamor/glu3/glu3_scalar.h @@ -0,0 +1,388 @@ +/* + * Copyright © 2009 Ian D. Romanick + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +extern inline void gluMult4v_4v(GLUvec4 *result, + const GLUvec4 *v1, const GLUvec4 *v2) +{ + result->values[0] = v1->values[0] * v2->values[0]; + result->values[1] = v1->values[1] * v2->values[1]; + result->values[2] = v1->values[2] * v2->values[2]; + result->values[3] = v1->values[3] * v2->values[3]; +} + + +extern inline void gluDiv4v_4v(GLUvec4 *result, + const GLUvec4 *v1, const GLUvec4 *v2) +{ + result->values[0] = v1->values[0] / v2->values[0]; + result->values[1] = v1->values[1] / v2->values[1]; + result->values[2] = v1->values[2] / v2->values[2]; + result->values[3] = v1->values[3] / v2->values[3]; +} + + +extern inline void gluAdd4v_4v(GLUvec4 *result, + const GLUvec4 *v1, const GLUvec4 *v2) +{ + result->values[0] = v1->values[0] + v2->values[0]; + result->values[1] = v1->values[1] + v2->values[1]; + result->values[2] = v1->values[2] + v2->values[2]; + result->values[3] = v1->values[3] + v2->values[3]; +} + + +extern inline void gluSub4v_4v(GLUvec4 *result, + const GLUvec4 *v1, const GLUvec4 *v2) +{ + result->values[0] = v1->values[0] - v2->values[0]; + result->values[1] = v1->values[1] - v2->values[1]; + result->values[2] = v1->values[2] - v2->values[2]; + result->values[3] = v1->values[3] - v2->values[3]; +} + + +extern inline void gluMult4v_f(GLUvec4 *result, + const GLUvec4 *v1, GLfloat f) +{ + result->values[0] = v1->values[0] * f; + result->values[1] = v1->values[1] * f; + result->values[2] = v1->values[2] * f; + result->values[3] = v1->values[3] * f; +} + + +extern inline void gluDiv4v_f(GLUvec4 *result, + const GLUvec4 *v1, GLfloat f) +{ + result->values[0] = v1->values[0] / f; + result->values[1] = v1->values[1] / f; + result->values[2] = v1->values[2] / f; + result->values[3] = v1->values[3] / f; +} + + +extern inline void gluAdd4v_f(GLUvec4 *result, + const GLUvec4 *v1, GLfloat f) +{ + result->values[0] = v1->values[0] + f; + result->values[1] = v1->values[1] + f; + result->values[2] = v1->values[2] + f; + result->values[3] = v1->values[3] + f; +} + + +extern inline void gluSub4v_f(GLUvec4 *result, + const GLUvec4 *v1, GLfloat f) +{ + result->values[0] = v1->values[0] - f; + result->values[1] = v1->values[1] - f; + result->values[2] = v1->values[2] - f; + result->values[3] = v1->values[3] - f; +} + + +extern inline void gluMult4m_f(GLUmat4 *result, + const GLUmat4 *m, GLfloat f) +{ + GLUmat4 temp; + + gluMult4v_f(& temp.col[0], & m->col[0], f); + gluMult4v_f(& temp.col[1], & m->col[1], f); + gluMult4v_f(& temp.col[2], & m->col[2], f); + gluMult4v_f(& temp.col[3], & m->col[3], f); + *result = temp; +} + + +extern inline void gluMult4m_4v(GLUvec4 *result, + const GLUmat4 *m, const GLUvec4 *v) +{ + GLUvec4 temp[6]; + unsigned i; + + for (i = 0; i < 4; i++) { + gluMult4v_f(& temp[i], & m->col[i], v->values[i]); + } + + gluAdd4v_4v(& temp[4], & temp[0], & temp[1]); + gluAdd4v_4v(& temp[5], & temp[2], & temp[3]); + gluAdd4v_4v(result, & temp[4], & temp[5]); +} + + +extern inline void gluAdd4m_4m(GLUmat4 *result, + const GLUmat4 *m1, const GLUmat4 *m2) +{ + GLUmat4 temp; + + gluAdd4v_4v(& temp.col[0], & m1->col[0], & m2->col[0]); + gluAdd4v_4v(& temp.col[1], & m1->col[1], & m2->col[1]); + gluAdd4v_4v(& temp.col[2], & m1->col[2], & m2->col[2]); + gluAdd4v_4v(& temp.col[3], & m1->col[3], & m2->col[3]); + *result = temp; +} + +extern inline void gluSub4m_4m(GLUmat4 *result, + const GLUmat4 *m1, const GLUmat4 *m2) +{ + GLUmat4 temp; + + gluSub4v_4v(& temp.col[0], & m1->col[0], & m2->col[0]); + gluSub4v_4v(& temp.col[1], & m1->col[1], & m2->col[1]); + gluSub4v_4v(& temp.col[2], & m1->col[2], & m2->col[2]); + gluSub4v_4v(& temp.col[3], & m1->col[3], & m2->col[3]); + *result = temp; +} + +extern inline GLfloat gluDot4_4v(const GLUvec4 *v1, const GLUvec4 *v2) +{ + return v1->values[0] * v2->values[0] + + v1->values[1] * v2->values[1] + + v1->values[2] * v2->values[2] + + v1->values[3] * v2->values[3]; +} + + +extern inline GLfloat gluDot3_4v(const GLUvec4 *v1, const GLUvec4 *v2) +{ + return v1->values[0] * v2->values[0] + + v1->values[1] * v2->values[1] + + v1->values[2] * v2->values[2]; +} + + +extern inline GLfloat gluDot2_4v(const GLUvec4 *v1, const GLUvec4 *v2) +{ + return v1->values[0] * v2->values[0] + + v1->values[1] * v2->values[1]; +} + + +extern inline void gluCross4v(GLUvec4 *result, + const GLUvec4 *v1, const GLUvec4 *v2) +{ + GLUvec4 temp; + + temp.values[0] = (v1->values[1] * v2->values[2]) + - (v1->values[2] * v2->values[1]); + temp.values[1] = (v1->values[2] * v2->values[0]) + - (v1->values[0] * v2->values[2]); + temp.values[2] = (v1->values[0] * v2->values[1]) + - (v1->values[1] * v2->values[0]); + temp.values[3] = 0.0; + *result = temp; +} + + +extern inline void gluOuter4v(GLUmat4 *result, + const GLUvec4 *v1, const GLUvec4 *v2) +{ + GLUmat4 temp; + + gluMult4v_f(& temp.col[0], v1, v2->values[0]); + gluMult4v_f(& temp.col[1], v1, v2->values[1]); + gluMult4v_f(& temp.col[2], v1, v2->values[2]); + gluMult4v_f(& temp.col[3], v1, v2->values[3]); + *result = temp; +} + + +extern inline GLfloat gluLengthSqr4v(const GLUvec4 *v) +{ + return gluDot4_4v(v, v); +} + + +extern inline GLfloat gluLength4v(const GLUvec4 *v) +{ + return sqrt(gluLengthSqr4v(v)); +} + + +extern inline void gluNormalize4v(GLUvec4 *result, const GLUvec4 *v) +{ + gluDiv4v_f(result, v, gluLength4v(v)); +} + + + +extern inline void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m) +{ + unsigned i; + unsigned j; + GLUmat4 temp; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp.col[i].values[j] = m->col[j].values[i]; + } + } + + *result = temp; +} + + +extern inline void gluMult4m_4m(GLUmat4 *result, + const GLUmat4 *m1, const GLUmat4 *m2) +{ + GLUmat4 temp; + unsigned i; + + for (i = 0; i < 4; i++) { + gluMult4m_4v(& temp.col[i], m1, & m2->col[i]); + } + + *result = temp; +} + + + +extern inline void gluTranslate3f(GLUmat4 *result, + GLfloat x, GLfloat y, GLfloat z) +{ + memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); + result->col[3].values[0] = x; + result->col[3].values[1] = y; + result->col[3].values[2] = z; +} + + +#ifdef __cplusplus +extern inline GLfloat gluDot4(const GLUvec4 &v1, const GLUvec4 &v2) +{ + return v1.values[0] * v2.values[0] + + v1.values[1] * v2.values[1] + + v1.values[2] * v2.values[2] + + v1.values[3] * v2.values[3]; +} + + +extern inline GLfloat gluDot3(const GLUvec4 &v1, const GLUvec4 &v2) +{ + return v1.values[0] * v2.values[0] + + v1.values[1] * v2.values[1] + + v1.values[2] * v2.values[2]; +} + + +extern inline GLfloat gluDot2(const GLUvec4 &v1, const GLUvec4 &v2) +{ + return v1.values[0] * v2.values[0] + + v1.values[1] * v2.values[1]; +} + + +inline GLUvec4 GLUvec4::operator+(const GLUvec4 &v) const +{ + return GLUvec4(values[0] + v.values[0], + values[1] + v.values[1], + values[2] + v.values[2], + values[3] + v.values[3]); +} + + +inline GLUvec4 GLUvec4::operator-(const GLUvec4 &v) const +{ + return GLUvec4(values[0] - v.values[0], + values[1] - v.values[1], + values[2] - v.values[2], + values[3] - v.values[3]); +} + + +inline GLUvec4 GLUvec4::operator*(const GLUvec4 &v) const +{ + return GLUvec4(values[0] * v.values[0], + values[1] * v.values[1], + values[2] * v.values[2], + values[3] * v.values[3]); +} + + +inline GLUvec4 GLUvec4::operator*(GLfloat f) const +{ + return GLUvec4(values[0] * f, + values[1] * f, + values[2] * f, + values[3] * f); +} + + +inline GLUvec4 GLUvec4::operator*(const GLUmat4 &m) const +{ + return GLUvec4(gluDot4(*this, m.col[0]), + gluDot4(*this, m.col[1]), + gluDot4(*this, m.col[2]), + gluDot4(*this, m.col[3])); +} + + +inline GLUmat4 GLUmat4::operator+(const GLUmat4 &m) const +{ + GLUmat4 temp; + + gluAdd4m_4m(& temp, this, &m); + return temp; +} + + +inline GLUmat4 GLUmat4::operator-(const GLUmat4 &m) const +{ + return GLUmat4(col[0] - m.col[0], + col[1] - m.col[1], + col[2] - m.col[2], + col[3] - m.col[3]); +} + + +inline GLUmat4 GLUmat4::operator*(GLfloat f) const +{ + GLUmat4 temp; + + gluMult4m_f(& temp, this, f); + return temp; +} + + +inline GLUvec4 GLUmat4::operator*(const GLUvec4 &v) const +{ + return (col[0] * v.values[0]) + + (col[1] * v.values[1]) + + (col[2] * v.values[2]) + + (col[3] * v.values[3]); +} + + +inline GLUmat4 GLUmat4::operator*(const GLUmat4 &m) const +{ + GLUmat4 temp; + + gluMult4m_4m(& temp, this, &m); + return temp; +} + + +#endif /* __cplusplus */ diff --git a/glamor/glu3/matrix.c b/glamor/glu3/matrix.c new file mode 100644 index 000000000..b3d5819f7 --- /dev/null +++ b/glamor/glu3/matrix.c @@ -0,0 +1,217 @@ +/* + * Copyright © 2009 Ian D. Romanick + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include "glu3.h" + +#define DEG2RAD(d) ((d) * M_PI / 180.0) + +const GLUmat4 gluIdentityMatrix = { + { + { { 1.0f, 0.0f, 0.0f, 0.0f } }, + { { 0.0f, 1.0f, 0.0f, 0.0f } }, + { { 0.0f, 0.0f, 1.0f, 0.0f } }, + { { 0.0f, 0.0f, 0.0f, 1.0f } } + } +}; + + +void gluTranslate4v(GLUmat4 *result, const GLUvec4 *t) +{ + memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); + result->col[3] = *t; + result->col[3].values[3] = 1.0f; +} + + +void gluScale4v(GLUmat4 *result, const GLUvec4 *t) +{ + memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); + result->col[0].values[0] = t->values[0]; + result->col[1].values[1] = t->values[1]; + result->col[2].values[2] = t->values[2]; +} + + +void gluLookAt4v(GLUmat4 *result, + const GLUvec4 *_eye, + const GLUvec4 *_center, + const GLUvec4 *_up) +{ + static const GLUvec4 col3 = { { 0.0f, 0.0f, 0.0f, 1.0f } }; + const GLUvec4 e = { + { -_eye->values[0], -_eye->values[1], -_eye->values[2], 0.0f } + }; + GLUmat4 translate; + GLUmat4 rotate; + GLUmat4 rotateT; + GLUvec4 f; + GLUvec4 s; + GLUvec4 u; + GLUvec4 center, up; + + center = *_center; + center.values[3] = 0; + up = *_up; + up.values[3] = 0; + + gluAdd4v_4v(& f, ¢er, &e); + gluNormalize4v(& f, & f); + + gluNormalize4v(& u, &up); + + gluCross4v(& s, & f, & u); + gluCross4v(& u, & s, & f); + + rotate.col[0] = s; + rotate.col[1] = u; + rotate.col[2].values[0] = -f.values[0]; + rotate.col[2].values[1] = -f.values[1]; + rotate.col[2].values[2] = -f.values[2]; + rotate.col[2].values[3] = 0.0f; + rotate.col[3] = col3; + gluTranspose4m(& rotateT, & rotate); + + gluTranslate4v(& translate, & e); + gluMult4m_4m(result, & rotateT, & translate); +} + + +void gluRotate4v(GLUmat4 *result, const GLUvec4 *_axis, GLfloat angle) +{ + GLUvec4 axis; + const float c = cos(angle); + const float s = sin(angle); + const float one_c = 1.0 - c; + + float xx; + float yy; + float zz; + + float xs; + float ys; + float zs; + + float xy; + float xz; + float yz; + + /* Only normalize the 3-component axis. A gluNormalize3v might be + * appropriate to save us some computation. + */ + axis = *_axis; + axis.values[3] = 0; + gluNormalize4v(&axis, &axis); + + xx = axis.values[0] * axis.values[0]; + yy = axis.values[1] * axis.values[1]; + zz = axis.values[2] * axis.values[2]; + + xs = axis.values[0] * s; + ys = axis.values[1] * s; + zs = axis.values[2] * s; + + xy = axis.values[0] * axis.values[1]; + xz = axis.values[0] * axis.values[2]; + yz = axis.values[1] * axis.values[2]; + + + result->col[0].values[0] = (one_c * xx) + c; + result->col[0].values[1] = (one_c * xy) + zs; + result->col[0].values[2] = (one_c * xz) - ys; + result->col[0].values[3] = 0.0; + + result->col[1].values[0] = (one_c * xy) - zs; + result->col[1].values[1] = (one_c * yy) + c; + result->col[1].values[2] = (one_c * yz) + xs; + result->col[1].values[3] = 0.0; + + + result->col[2].values[0] = (one_c * xz) + ys; + result->col[2].values[1] = (one_c * yz) - xs; + result->col[2].values[2] = (one_c * zz) + c; + result->col[2].values[3] = 0.0; + + result->col[3].values[0] = 0.0; + result->col[3].values[1] = 0.0; + result->col[3].values[2] = 0.0; + result->col[3].values[3] = 1.0; +} + + +void +gluPerspective4f(GLUmat4 *result, + GLfloat fovy, GLfloat aspect, GLfloat near, GLfloat far) +{ + const double sine = sin(DEG2RAD(fovy / 2.0)); + const double cosine = cos(DEG2RAD(fovy / 2.0)); + const double sine_aspect = sine * aspect; + const double dz = far - near; + + + memcpy(result, &gluIdentityMatrix, sizeof(gluIdentityMatrix)); + if ((sine == 0.0) || (dz == 0.0) || (sine_aspect == 0.0)) { + return; + } + + result->col[0].values[0] = cosine / sine_aspect; + result->col[1].values[1] = cosine / sine; + result->col[2].values[2] = -(far + near) / dz; + result->col[2].values[3] = -1.0; + result->col[3].values[2] = -2.0 * near * far / dz; + result->col[3].values[3] = 0.0; +} + +void gluFrustum6f(GLUmat4 *result, + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far) +{ + memcpy(result, &gluIdentityMatrix, sizeof(gluIdentityMatrix)); + + result->col[0].values[0] = (2.0 * near) / (right - left); + result->col[1].values[1] = (2.0 * near) / (top - bottom); + result->col[2].values[0] = (right + left) / (right - left); + result->col[2].values[1] = (top + bottom) / (top - bottom); + result->col[2].values[2] = -(far + near) / (far - near); + result->col[2].values[3] = -1.0; + result->col[3].values[2] = -2.0 * near * far / (far - near); + result->col[3].values[3] = 0.0; +} + +void gluOrtho6f(GLUmat4 *result, + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far) +{ + memcpy(result, &gluIdentityMatrix, sizeof(gluIdentityMatrix)); + + result->col[0].values[0] = 2.0f / (right - left); + result->col[3].values[0] = -(right + left) / (right - left); + + result->col[1].values[1] = 2.0f / (top - bottom); + result->col[3].values[1] = -(top + bottom) / (top - bottom); + + result->col[2].values[2] = -2.0f / (far - near); + result->col[3].values[2] = -(far + near) / (far - near); +} From 8a53566acb5870816807425dc805df888fa42792 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 25 Aug 2009 13:06:11 -0700 Subject: [PATCH 040/462] glamor: make the polylines complaint a little more useful. --- glamor/glamor_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 58cb35716..addff1ac7 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -285,9 +285,13 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, int i; /* Don't try to do wide lines or non-solid fill style. */ - if (gc->lineWidth != 0 || gc->lineStyle != LineSolid || + if (gc->lineWidth != 0) { + ErrorF("stub wide polylines\n"); + return; + } + if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { - ErrorF("stub poly_line depth %d\n", drawable->depth); + ErrorF("stub poly_line non-solid fill\n"); return; } From 854e9bd20a2d0f8ed636d4fba0ddfa4c71d54667 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 25 Aug 2009 16:56:50 -0700 Subject: [PATCH 041/462] glamor: Add untested PutImage XYBitmap support. --- glamor/glamor.c | 1 + glamor/glamor_priv.h | 7 ++ glamor/glamor_putimage.c | 202 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 43e1c7d3a..71c8ab20f 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -208,6 +208,7 @@ glamor_init(ScreenPtr screen) glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); + glamor_init_putimage_shaders(screen); glamor_init_composite_shaders(screen); return TRUE; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 864be51ab..b5ba82d12 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -63,6 +63,12 @@ typedef struct glamor_screen_private { GLint tile_prog; glamor_transform_uniforms tile_transform; + /* 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[2]; } glamor_screen_private; @@ -163,6 +169,7 @@ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits); +void glamor_init_putimage_shaders(ScreenPtr screen); /* glamor_render.c */ void glamor_composite(CARD8 op, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index a0b8635dd..07052358c 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -32,6 +32,201 @@ */ #include "glamor_priv.h" +void +glamor_init_putimage_shaders(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + const char *xybitmap_vs = + "uniform float x_bias;\n" + "uniform float x_scale;\n" + "uniform float y_bias;\n" + "uniform float y_scale;\n" + "varying vec2 bitmap_coords;\n" + "void main()\n" + "{\n" + " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" + " (gl_Vertex.y + y_bias) * y_scale,\n" + " 0,\n" + " 1);\n" + " bitmap_coords = gl_MultiTexCoord0.xy;\n" + "}\n"; + const char *xybitmap_fs = + "uniform vec4 fg, bg;\n" + "varying vec2 bitmap_coords;\n" + "uniform sampler2D bitmap_sampler;\n" + "void main()\n" + "{\n" + " float bitmap_value = texture2D(bitmap_sampler,\n" + " bitmap_coords).x;\n" + " gl_FragColor = mix(bg, fg, bitmap_value);\n" + "}\n"; + GLint fs_prog, vs_prog, prog; + GLint sampler_uniform_location; + + if (!GLEW_ARB_fragment_shader) + return; + + prog = glCreateProgramObjectARB(); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, xybitmap_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, xybitmap_fs); + glAttachObjectARB(prog, vs_prog); + glAttachObjectARB(prog, fs_prog); + glamor_link_glsl_prog(prog); + + glUseProgramObjectARB(prog); + sampler_uniform_location = glGetUniformLocationARB(prog, "bitmap_sampler"); + glUniform1iARB(sampler_uniform_location, 0); + + glamor_priv->put_image_xybitmap_fg_uniform_location = + glGetUniformLocationARB(prog, "fg"); + glamor_priv->put_image_xybitmap_bg_uniform_location = + glGetUniformLocationARB(prog, "bg"); + glamor_get_transform_uniform_locations(prog, + &glamor_priv->put_image_xybitmap_transform); + glamor_priv->put_image_xybitmap_prog = prog; + glUseProgramObjectARB(0); +} + +static int +y_flip(PixmapPtr pixmap, int y) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + + if (pixmap == screen_pixmap) + return (pixmap->drawable.height - 1) - y; + else + return y; +} + +/* Do an XYBitmap putimage. The bits are byte-aligned rows of bitmap + * data (where each row starts at a bit index of left_pad), and the + * destination gets filled with the gc's fg color where the bitmap is set + * and the bg color where the bitmap is unset. + * + * Implement this by passing the bitmap right through to GL, and sampling + * it to choose between fg and bg in the fragment shader. The driver may + * be exploding the bitmap up to be an 8-bit alpha texture, in which + * case we might be better off just doing the fg/bg choosing in the CPU + * and just draw the resulting texture to the destination. + */ +static void +glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, + int x, int y, int w, int h, int left_pad, + int image_format, char *bits) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + float fg[4], bg[4]; + GLuint tex; + unsigned int stride = PixmapBytePad(1, w + left_pad); + RegionPtr clip; + BoxPtr box; + int nbox; + float dest_coords[8] = { + x, y, + x + w, y, + x + w, y + h, + x, y + h, + }; + const float bitmap_coords[8] = { + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + }; + + if (glamor_priv->put_image_xybitmap_prog == 0) { + ErrorF("no program for xybitmap putimage\n"); + goto fail; + } + + glamor_set_alu(gc->alu); + if (!glamor_set_planemask(pixmap, gc->planemask)) + goto fail; + + glUseProgramObjectARB(glamor_priv->put_image_xybitmap_prog); + + glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); + glUniform4fvARB(glamor_priv->put_image_xybitmap_fg_uniform_location, + 1, fg); + glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); + glUniform4fvARB(glamor_priv->put_image_xybitmap_bg_uniform_location, + 1, bg); + + glamor_set_transform_for_pixmap(pixmap, &glamor_priv->solid_transform); + + glGenTextures(1, &tex); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, + w, h, 0, + GL_COLOR_INDEX, GL_BITMAP, bits); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glEnable(GL_TEXTURE_2D); + + /* Now that we've set up our bitmap texture and the shader, shove + * the destination rectangle through the cliprects and run the + * shader on the resulting fragments. + */ + glVertexPointer(2, GL_FLOAT, 0, dest_coords); + glEnableClientState(GL_VERTEX_ARRAY); + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glEnable(GL_SCISSOR_TEST); + clip = fbGetCompositeClip(gc); + for (nbox = REGION_NUM_RECTS(clip), + box = REGION_RECTS(clip); + nbox--; + box++) + { + int x1 = x; + int y1 = y; + int x2 = x + w; + int y2 = y + h; + + if (x1 < box->x1) + x1 = box->x1; + if (y1 < box->y1) + y1 = box->y1; + if (x2 > box->x2) + x2 = box->x2; + if (y2 > box->y2) + y2 = box->y2; + if (x1 >= x2 || y1 >= y2) + continue; + + glScissor(box->x1, + y_flip(pixmap, box->y1), + box->x2 - box->x1, + box->y2 - box->y1); + glDrawArrays(GL_QUADS, 0, 4); + } + + glDisable(GL_SCISSOR_TEST); + glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); + glDeleteTextures(1, &tex); + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + return; + +fail: + glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); + glamor_solid_fail_region(pixmap, x, y, w, h); +} + void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int left_pad, int image_format, char *bits) @@ -50,6 +245,13 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, return; } + if (image_format == XYBitmap) { + assert(depth == 1); + glamor_put_image_xybitmap(drawable, gc, x, y, w, h, + left_pad, image_format, bits); + return; + } + if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; if (image_format != ZPixmap) { From 6dacc9b08c2af51c1826c20ccf12bb2c73856f25 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 25 Aug 2009 17:01:43 -0700 Subject: [PATCH 042/462] glamor: Add untested PutImage 1bpp XYPixmap support. --- glamor/glamor_putimage.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 07052358c..55854daae 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -252,18 +252,21 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, return; } + if (bpp == 1 && image_format == XYPixmap) + image_format = ZPixmap; + if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; if (image_format != ZPixmap) { ErrorF("putimage: non-ZPixmap\n"); goto fail; } - if (bpp < 8) { - ErrorF("putimage: bad bpp: %d\n", bpp); - goto fail; - } switch (drawable->depth) { + case 1: + format = GL_COLOR_INDEX; + type = GL_BITMAP; + break; case 8: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; @@ -279,7 +282,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, default: ErrorF("stub put_image depth %d\n", drawable->depth); goto fail; - break; } glamor_set_alu(gc->alu); @@ -288,7 +290,9 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, y += drawable->y; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride / (bpp / 8)); + glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / bpp); + if (bpp == 1) + glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); clip = fbGetCompositeClip(gc); for (nbox = REGION_NUM_RECTS(clip), pbox = REGION_RECTS(clip); @@ -320,6 +324,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, src); } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); return; From 936385142c12d074dcb603490517ac095840fa3f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 25 Aug 2009 17:24:30 -0700 Subject: [PATCH 043/462] glamor: Accelerate PolyFillRect using glamor_fill instead of spans. --- glamor/Makefile.am | 1 + glamor/glamor_core.c | 2 +- glamor/glamor_polyfillrect.c | 118 +++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 7 +++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 glamor/glamor_polyfillrect.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 4d307fe7a..3035f6323 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -21,6 +21,7 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ + glamor_polyfillrect.c \ glamor_putimage.c \ glamor_setspans.c \ glamor_render.c \ diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index addff1ac7..7b96d674a 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -352,7 +352,7 @@ GCOps glamor_gc_ops = { .PolyRectangle = miPolyRectangle, .PolyArc = miPolyArc, .FillPolygon = miFillPolygon, - .PolyFillRect = miPolyFillRect, + .PolyFillRect = glamor_poly_fill_rect, .PolyFillArc = miPolyFillArc, .PolyText8 = miPolyText8, .PolyText16 = miPolyText16, diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c new file mode 100644 index 000000000..ae8963dac --- /dev/null +++ b/glamor/glamor_polyfillrect.c @@ -0,0 +1,118 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_fillspans.c + * + * GC PolyFillRect implementation, taken straight from fb_fill.c + */ + +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, + int nrect, + xRectangle *prect) +{ + RegionPtr clip = fbGetCompositeClip(gc); + register BoxPtr box; + BoxPtr pextent; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1, fullY2; + int partX1, partX2, partY1, partY2; + int xorg, yorg; + int n; + + xorg = drawable->x; + yorg = drawable->y; + + pextent = REGION_EXTENTS(gc->pScreen, clip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (nrect--) + { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int)prect->width; + fullY2 = fullY1 + (int)prect->height; + prect++; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullY1 < extentY1) + fullY1 = extentY1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullY2 > extentY2) + fullY2 = extentY2; + + if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) + continue; + n = REGION_NUM_RECTS(clip); + if (n == 1) { + glamor_fill(drawable, + gc, + fullX1, fullY1, fullX2-fullX1, fullY2-fullY1); + } else { + box = REGION_RECTS(clip); + /* clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect() + */ + while (n--) { + partX1 = box->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partY1 = box->y1; + if (partY1 < fullY1) + partY1 = fullY1; + partX2 = box->x2; + if (partX2 > fullX2) + partX2 = fullX2; + partY2 = box->y2; + if (partY2 > fullY2) + partY2 = fullY2; + + box++; + + if (partX1 < partX2 && partY1 < partY2) + glamor_fill(drawable, gc, + partX1, partY1, + partX2 - partX1, partY2 - partY1); + } + } + } +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b5ba82d12..3ad18b5f5 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -165,6 +165,13 @@ glamor_get_spans(DrawablePtr drawable, void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted); +/* glamor_polyfillrect.c */ +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, + int nrect, + xRectangle *prect); + /* glamor_putimage.c */ void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, From 1159ebb30b7530c2f4612109306cf85a594dd530 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 4 Sep 2009 18:43:02 -0700 Subject: [PATCH 044/462] glamor: Add untested copyarea implementation --- glamor/Makefile.am | 1 + glamor/glamor_copyarea.c | 116 +++++++++++++++++++++++++++++++++++++++ glamor/glamor_core.c | 2 +- glamor/glamor_priv.h | 4 ++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 glamor/glamor_copyarea.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 3035f6323..838aedcd6 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -17,6 +17,7 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ + glamor_copyarea.c \ glamor_core.c \ glamor_fill.c \ glamor_fillspans.c \ diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c new file mode 100644 index 000000000..876892213 --- /dev/null +++ b/glamor/glamor_copyarea.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2008 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_copyarea.c + * + * GC CopyArea implementation + */ + +static void +glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + int i; + + glamor_set_alu(gc->alu); + if (!glamor_set_planemask(dst_pixmap, gc->planemask)) + goto fail; + + for (i = 0; i < nbox; i++) { + glRasterPos2i(box[i].x1 - dst_pixmap->screen_x, + box[i].y1 - dst_pixmap->screen_y); + glCopyPixels(box[i].x1 + dx - src_pixmap->screen_x, + box[i].y1 + dy - src_pixmap->screen_y, + box[i].x2 - box[i].x1, + box[i].y2 - box[i].y1, + GL_RGBA); + } + +fail: + glamor_set_alu(GXcopy); + glamor_set_planemask(dst_pixmap, ~0); +} + +RegionPtr +glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + ScreenPtr screen = dst->pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src); + RegionPtr region; + + if (!GLEW_EXT_framebuffer_blit) { + ErrorF("EXT_framebuffer_blit unsupported\n"); + goto fail; + } + + if (!glamor_set_destination_pixmap(dst_pixmap)) { + /* + return miDoCopy(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, fbCopyNtoN, 0, NULL); + */ + return NULL; + } + + if (src_priv == NULL) { + ErrorF("glamor_copy_area: no src pixmap priv?"); + goto fail; + } + + if (src_priv->fb == 0 && src_pixmap != screen_pixmap) { + ErrorF("glamor_copy_area: No src FBO\n"); + return NULL; + } + + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src_priv->fb); + + region = miDoCopy(src, dst, gc, + srcx, srcy, width, height, + dstx, dsty, glamor_copy_n_to_n, 0, NULL); + + return region; + +fail: + return NULL; +} diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 7b96d674a..c31e23ced 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -344,7 +344,7 @@ GCOps glamor_gc_ops = { .FillSpans = glamor_fill_spans, .SetSpans = glamor_set_spans, .PutImage = glamor_put_image, - .CopyArea = miCopyArea, + .CopyArea = glamor_copy_area, .CopyPlane = miCopyPlane, .PolyPoint = miPolyPoint, .Polylines = glamor_poly_lines, diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3ad18b5f5..1e2a17357 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -110,6 +110,10 @@ glamor_pm_is_solid(DrawablePtr drawable, unsigned long planemask) /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); +/* glamor_copyarea.c */ +RegionPtr +glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int width, int height, int dstx, int dsty); /* glamor_core.c */ Bool glamor_create_gc(GCPtr gc); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, From 5915b4c0cfcfb25a68b77b29a4d7b39b7f6b4822 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 4 Sep 2009 18:43:52 -0700 Subject: [PATCH 045/462] glamor: Add support for solid source pictures. --- glamor/glamor_priv.h | 4 +- glamor/glamor_render.c | 218 +++++++++++++++++++++++++++++------------ 2 files changed, 159 insertions(+), 63 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1e2a17357..93a0115e1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -43,6 +43,8 @@ typedef struct glamor_composite_shader { 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 glamor_screen_private { @@ -70,7 +72,7 @@ typedef struct glamor_screen_private { GLint put_image_xybitmap_bg_uniform_location; /* glamor_composite */ - glamor_composite_shader composite_shader[2]; + glamor_composite_shader composite_shader[8]; } glamor_screen_private; typedef struct glamor_pixmap_private { diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index d0c955792..2ebb4c5c9 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -39,7 +39,9 @@ #include "glu3/glu3.h" struct shader_key { + Bool solid_source; Bool has_mask; + Bool solid_mask; }; struct blendinfo { @@ -65,7 +67,9 @@ static struct blendinfo composite_op_info[] = { [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, }; -#define HAS_MASK_INDEX 1 +#define SOLID_SOURCE_INDEX 1 +#define HAS_MASK_INDEX 2 +#define SOLID_MASK_INDEX 3 static glamor_composite_shader * glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) @@ -73,8 +77,13 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int index = 0; - if (key->has_mask) + if (key->solid_source) + index += SOLID_SOURCE_INDEX; + if (key->has_mask) { index += HAS_MASK_INDEX; + if (key->solid_mask) + index += SOLID_MASK_INDEX; + } assert(index < ARRAY_SIZE(glamor_priv->composite_shader)); @@ -84,31 +93,58 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) static GLuint glamor_create_composite_fs(struct shader_key *key) { - const char *header = + const char *source_pixmap_header = "uniform sampler2D source_sampler;\n" "varying vec4 source_coords;\n"; - const char *mask_header = + const char *source_solid_header = + "uniform vec4 source;\n"; + const char *mask_pixmap_header = "uniform sampler2D mask_sampler;\n" "varying vec4 mask_coords;\n"; + const char *mask_solid_header = + "uniform vec4 mask;\n"; const char *main_opening = "void main()\n" - "{\n" - " vec4 result;\n" - " result = texture2DProj(source_sampler, source_coords.xyw);\n"; + "{\n"; + const char *source_pixmap_fetch = + " vec4 source = texture2DProj(source_sampler, " + " source_coords.xyw);\n"; + const char *mask_pixmap_fetch = + " vec4 mask = texture2DProj(mask_sampler, mask_coords.xyw);\n"; const char *source_in_mask = - " vec4 mask = texture2DProj(mask_sampler, mask_coords.xyw);\n" - " result = result * mask.w;\n"; + " gl_FragColor = source * mask.w;\n"; + const char *source_only = + " gl_FragColor = source;\n"; const char *main_closing = - " gl_FragColor = result;\n" "}\n"; char *source; + const char *source_setup = ""; + const char *source_fetch = ""; + const char *mask_setup = ""; + const char *mask_fetch = ""; GLuint prog; - source = XNFprintf("%s%s%s%s%s", - header, - key->has_mask ? mask_header : "", + if (key->solid_source) { + source_setup = source_solid_header; + } else { + source_setup = source_pixmap_header; + source_fetch = source_pixmap_fetch; + } + if (key->has_mask) { + if (key->solid_mask) { + mask_setup = mask_solid_header; + } else { + mask_setup = mask_pixmap_header; + mask_fetch = mask_pixmap_fetch; + } + } + source = XNFprintf("%s%s%s%s%s%s%s", + source_setup, + mask_setup, main_opening, - key->has_mask ? source_in_mask : "", + source_fetch, + mask_fetch, + key->has_mask ? source_in_mask : source_only, main_closing); prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); @@ -139,12 +175,13 @@ glamor_create_composite_vs(struct shader_key *key) "}\n"; char *source; GLuint prog; + Bool compute_mask_coords = key->has_mask && !key->solid_mask; source = XNFprintf("%s%s%s%s%s", header, - key->has_mask ? mask_header : "", + compute_mask_coords ? mask_header : "", main_opening, - key->has_mask ? mask_coords : "", + compute_mask_coords ? mask_coords : "", main_closing); prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); @@ -177,20 +214,31 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) shader->prog = prog; glUseProgramObjectARB(prog); - source_sampler_uniform_location = glGetUniformLocationARB(prog, - "source_sampler"); shader->dest_to_dest_uniform_location = glGetUniformLocationARB(prog, "dest_to_dest"); - shader->dest_to_source_uniform_location = - glGetUniformLocationARB(prog, "dest_to_source"); - glUniform1i(source_sampler_uniform_location, 0); + + if (key->solid_source) { + shader->source_uniform_location = glGetUniformLocationARB(prog, + "source"); + } else { + source_sampler_uniform_location = glGetUniformLocationARB(prog, + "source_sampler"); + shader->dest_to_source_uniform_location = + glGetUniformLocationARB(prog, "dest_to_source"); + glUniform1i(source_sampler_uniform_location, 0); + } if (key->has_mask) { - mask_sampler_uniform_location = glGetUniformLocationARB(prog, - "mask_sampler"); - glUniform1i(mask_sampler_uniform_location, 1); - shader->dest_to_mask_uniform_location = - glGetUniformLocationARB(prog, "dest_to_mask"); + if (key->solid_mask) { + shader->mask_uniform_location = glGetUniformLocationARB(prog, + "mask"); + } else { + mask_sampler_uniform_location = glGetUniformLocationARB(prog, + "mask_sampler"); + glUniform1i(mask_sampler_uniform_location, 1); + shader->dest_to_mask_uniform_location = + glGetUniformLocationARB(prog, "dest_to_mask"); + } } } @@ -199,10 +247,21 @@ glamor_init_composite_shaders(ScreenPtr screen) { struct shader_key key; + memset(&key, 0, sizeof(key)); key.has_mask = FALSE; glamor_create_composite_shader(screen, &key); key.has_mask = TRUE; glamor_create_composite_shader(screen, &key); + key.solid_mask = TRUE; + glamor_create_composite_shader(screen, &key); + + key.solid_source = TRUE; + key.has_mask = FALSE; + glamor_create_composite_shader(screen, &key); + key.has_mask = TRUE; + glamor_create_composite_shader(screen, &key); + key.solid_mask = TRUE; + glamor_create_composite_shader(screen, &key); } static void @@ -277,8 +336,12 @@ glamor_set_composite_op(ScreenPtr screen, static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, - glamor_pixmap_private *pixmap_priv) + glamor_pixmap_private *pixmap_priv, + GLint transform_uniform_location, + int x_translate, int y_translate) { + GLUmat4 transform; + glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); switch (picture->repeatType) { @@ -313,6 +376,27 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, } glEnable(GL_TEXTURE_2D); + + glamor_set_composite_transform_matrix(&transform, + picture, + x_translate, + y_translate); + glUniformMatrix4fvARB(transform_uniform_location, 1, 0, + (float *)&transform); +} + +static void +glamor_set_composite_solid(PicturePtr picture, GLint uniform_location) +{ + 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; + + glUniform4fvARB(uniform_location, 1, color); } void @@ -332,10 +416,11 @@ glamor_composite(CARD8 op, ScreenPtr screen = dest->pDrawable->pScreen; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); PixmapPtr source_pixmap, mask_pixmap = NULL; - glamor_pixmap_private *source_pixmap_priv, *mask_pixmap_priv = NULL; + glamor_pixmap_private *source_pixmap_priv = NULL; + glamor_pixmap_private *mask_pixmap_priv = NULL; struct shader_key key; glamor_composite_shader *shader; - GLUmat4 dest_to_dest, dest_to_source, dest_to_mask; + GLUmat4 dest_to_dest; RegionRec region; int i; @@ -358,14 +443,23 @@ glamor_composite(CARD8 op, return; } + memset(&key, 0, sizeof(key)); key.has_mask = (mask != NULL); if (!source->pDrawable) { - ErrorF("source-only source\n"); - goto fail; + if (source->pSourcePict->type == SourcePictTypeSolidFill) { + key.solid_source = TRUE; + } else { + ErrorF("gradient source\n"); + goto fail; + } } if (mask && !mask->pDrawable) { - ErrorF("source-only mask\n"); - goto fail; + if (mask->pSourcePict->type == SourcePictTypeSolidFill) { + key.solid_mask = TRUE; + } else { + ErrorF("gradient mask\n"); + goto fail; + } } if (source->alphaMap) { ErrorF("source alphaMap\n"); @@ -376,17 +470,19 @@ glamor_composite(CARD8 op, goto fail; } - source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (source_pixmap == dest_pixmap) { - ErrorF("source == dest\n"); - goto fail; + if (!key.solid_source) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (source_pixmap == dest_pixmap) { + ErrorF("source == dest\n"); + goto fail; + } + if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { + ErrorF("no FBO in source\n"); + goto fail; + } } - if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { - ErrorF("no FBO in source\n"); - goto fail; - } - if (mask) { + if (mask && !key.solid_mask) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); if (mask_pixmap == dest_pixmap) { @@ -431,25 +527,23 @@ glamor_composite(CARD8 op, -1, 1); glUniformMatrix4fvARB(shader->dest_to_dest_uniform_location, 1, 0, (float *)&dest_to_dest); - glamor_set_composite_transform_matrix(&dest_to_source, - source, - x_source - x_dest, - y_source - x_dest); - glUniformMatrix4fvARB(shader->dest_to_source_uniform_location, 1, 0, - (float *)&dest_to_source); - if (mask) { - glamor_set_composite_transform_matrix(&dest_to_mask, - mask, - x_mask - x_dest, - y_mask - x_dest); - glUniformMatrix4fvARB(shader->dest_to_mask_uniform_location, 1, 0, - (float *)&dest_to_mask); + if (key.solid_source) { + glamor_set_composite_solid(source, shader->source_uniform_location); + } else { + glamor_set_composite_texture(screen, 0, source, source_pixmap_priv, + shader->dest_to_source_uniform_location, + x_source - x_dest, y_source - y_dest); + } + if (key.has_mask) { + if (key.solid_mask) { + glamor_set_composite_solid(mask, shader->mask_uniform_location); + } else { + glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv, + shader->dest_to_mask_uniform_location, + x_mask - x_dest, y_mask - y_dest); + } } - - glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); - if (mask) - glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); if (!miComputeCompositeRegion(®ion, source, mask, dest, @@ -469,9 +563,9 @@ glamor_composite(CARD8 op, } glEnd(); - glamor_set_composite_op(screen, PictOpSrc, dest, mask); + glDisable(GL_BLEND); glUseProgramObjectARB(0); - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return; From f17473cdd5f93a2bf3a7b6a14bd5acd965e8e9f0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 22 Sep 2009 10:55:04 -0700 Subject: [PATCH 046/462] glamor: Fix pixmap private getter in copyarea. --- glamor/glamor_copyarea.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 876892213..6f2911a1c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -76,7 +76,7 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src); + glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); RegionPtr region; if (!GLEW_EXT_framebuffer_blit) { From c4343dfa0a2b40d46d3feb14f1df9fae0fd4a214 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 22 Sep 2009 12:08:19 -0700 Subject: [PATCH 047/462] glamor: Add prepare/finishaccess code based on UXA. --- glamor/glamor.c | 12 +++ glamor/glamor_core.c | 245 ++++++++++++++++++++++++++++++++++++++++++- glamor/glamor_priv.h | 14 +++ 3 files changed, 269 insertions(+), 2 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 71c8ab20f..507a19be4 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -177,6 +177,10 @@ glamor_init(ScreenPtr screen) ErrorF("GL_ARB_vertex_shader required\n"); goto fail; } + if (!GLEW_ARB_pixel_buffer_object) { + ErrorF("GL_ARB_pixel_buffer_object required\n"); + goto fail; + } if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, @@ -199,6 +203,12 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_get_image = screen->GetImage; screen->GetImage = miGetImage; + glamor_priv->saved_change_window_attributes = screen->ChangeWindowAttributes; + screen->ChangeWindowAttributes = glamor_change_window_attributes; + + glamor_priv->saved_bitmap_to_region = screen->BitmapToRegion; + screen->BitmapToRegion = glamor_bitmap_to_region; + #ifdef RENDER glamor_priv->saved_composite = ps->Composite; ps->Composite = glamor_composite; @@ -231,6 +241,8 @@ glamor_fini(ScreenPtr screen) screen->CreatePixmap = glamor_priv->saved_create_pixmap; screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; screen->GetSpans = glamor_priv->saved_get_spans; + screen->ChangeWindowAttributes = glamor_priv->saved_change_window_attributes; + screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; #ifdef RENDER ps->Composite = glamor_priv->saved_composite; #endif diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index c31e23ced..3c98b5cb0 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -260,6 +260,129 @@ glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, } } +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; + GLenum format, type; + + if (pixmap_priv == NULL) + 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 = PixmapBytePad(drawable->width, drawable->depth); + + 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: + format = GL_RGB; + type = GL_UNSIGNED_BYTE; + break; + 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; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glGenBuffersARB(1, &pixmap_priv->pbo); + glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, stride * drawable->height, + NULL, GL_DYNAMIC_DRAW_ARB); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, stride * 8 / + pixmap->drawable.bitsPerPixel); + + glReadPixels(0, 0, + pixmap->drawable.width, pixmap->drawable.height, + format, type, 0); + + pixmap->devPrivate.ptr = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, + GL_READ_WRITE_ARB); + + return TRUE; +} + +void +glamor_finish_access(DrawablePtr drawable) +{ + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + unsigned int stride; + GLenum format, type; + + if (pixmap_priv == NULL) + return; + + if (pixmap_priv->fb == 0) { + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + + if (pixmap != screen_pixmap) + return; + } + + glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); + glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); + pixmap->devPrivate.ptr = NULL; + + stride = PixmapBytePad(drawable->width, drawable->depth); + + 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: + format = GL_RGB; + type = GL_UNSIGNED_BYTE; + break; + case 32: + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + default: + ErrorF("Unknown finishaccess depth %d\n", drawable->depth); + return; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8 / + pixmap->drawable.bitsPerPixel); + + glRasterPos2i(0, 0); + glDrawPixels(pixmap->drawable.width, pixmap->drawable.height, + format, type, 0); + glDeleteBuffersARB(1, &pixmap_priv->pbo); + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); +} + void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, @@ -364,13 +487,78 @@ GCOps glamor_gc_ops = { }; /** - * exaValidateGC() sets the ops to EXA's implementations, which may be + * uxa_validate_gc() sets the ops to glamor's implementations, which may be * accelerated or may sync the card and fall back to fb. */ static void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) { - fbValidateGC(gc, changes, 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. + */ +#ifdef FB_24_32BIT + if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { + gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); + fbGetRotatedPixmap(gc) = 0; + } + + 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)) + { + if (glamor_prepare_access(&gc->tile.pixmap->drawable, + GLAMOR_ACCESS_RW)) { + fbPadPixmap(gc->tile.pixmap); + glamor_finish_access(&gc->tile.pixmap->drawable); + } + } + /* Mask out the GCTile change notification, now that we've done FB's + * job for it. + */ + 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); + } + } else { + fbValidateGC(gc, changes, drawable); + } gc->ops = &glamor_gc_ops; } @@ -399,3 +587,56 @@ glamor_create_gc(GCPtr gc) 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->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; +} + +void +glamor_finish_access_window(WindowPtr window) +{ + if (window->backgroundState == BackgroundPixmap) + glamor_finish_access(&window->background.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; + + if (!glamor_prepare_access_window(window)) + return FALSE; + ret = fbChangeWindowAttributes(window, mask); + glamor_finish_access_window(window); + return ret; +} + +RegionPtr +glamor_bitmap_to_region(PixmapPtr pixmap) +{ + RegionPtr ret; + if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) + return NULL; + ret = fbPixmapToRegion(pixmap); + glamor_finish_access(&pixmap->drawable); + return ret; +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 93a0115e1..81bb035f5 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -31,6 +31,11 @@ #include "glamor.h" #include +typedef enum glamor_access { + GLAMOR_ACCESS_RO, + GLAMOR_ACCESS_RW, +} glamor_access_t; + typedef struct glamor_transform_uniforms { GLint x_bias; GLint x_scale; @@ -55,6 +60,8 @@ typedef struct glamor_screen_private { GetImageProcPtr saved_get_image; CompositeProcPtr saved_composite; TrapezoidsProcPtr saved_trapezoids; + ChangeWindowAttributesProcPtr saved_change_window_attributes; + BitmapToRegionProcPtr saved_bitmap_to_region; /* glamor_solid */ GLint solid_prog; @@ -78,6 +85,7 @@ typedef struct glamor_screen_private { typedef struct glamor_pixmap_private { GLuint tex; GLuint fb; + GLuint pbo; } glamor_pixmap_private; extern DevPrivateKey glamor_screen_private_key; @@ -117,6 +125,10 @@ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, int srcx, int srcy, int width, int height, int dstx, int dsty); /* glamor_core.c */ +Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access); +void glamor_finish_access(DrawablePtr drawable); +Bool glamor_prepare_access_window(WindowPtr window); +void glamor_finish_access_window(WindowPtr window); Bool glamor_create_gc(GCPtr gc); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, @@ -134,6 +146,8 @@ void glamor_get_transform_uniform_locations(GLint prog, glamor_transform_uniforms *uniform_locations); void glamor_set_transform_for_pixmap(PixmapPtr pixmap, glamor_transform_uniforms *uniform_locations); +Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); +RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); /* glamor_fill.c */ void glamor_fill(DrawablePtr drawable, From 800fd4f8494ad6f0984073406b3dec584ba63648 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 22 Sep 2009 15:41:18 -0700 Subject: [PATCH 048/462] glamor: Fix the type for copyarea. --- glamor/glamor_copyarea.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 6f2911a1c..c89dffcba 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -60,7 +60,7 @@ glamor_copy_n_to_n(DrawablePtr src, box[i].y1 + dy - src_pixmap->screen_y, box[i].x2 - box[i].x1, box[i].y2 - box[i].y1, - GL_RGBA); + GL_COLOR); } fail: From ca58607a44c310ef369a097a06be83aa2a9e1c5b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 09:58:55 +0100 Subject: [PATCH 049/462] glamor: Move glamor_poly_lines to a separate file. --- glamor/Makefile.am | 1 + glamor/glamor_core.c | 133 +++++++++++++------------------------- glamor/glamor_polylines.c | 107 ++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 5 ++ 4 files changed, 159 insertions(+), 87 deletions(-) create mode 100644 glamor/glamor_polylines.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 838aedcd6..ce7869244 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -23,6 +23,7 @@ libglamor_la_SOURCES = \ glamor_fillspans.c \ glamor_getspans.c \ glamor_polyfillrect.c \ + glamor_polylines.c \ glamor_putimage.c \ glamor_setspans.c \ glamor_render.c \ diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 3c98b5cb0..4ae0d6c78 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -265,8 +265,9 @@ 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; + unsigned int stride, read_stride, x, y; GLenum format, type; + uint8_t *data, *read; if (pixmap_priv == NULL) return TRUE; @@ -280,11 +281,15 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) } stride = PixmapBytePad(drawable->width, drawable->depth); + read_stride = stride; + + data = xalloc(stride * drawable->height); switch (drawable->depth) { case 1: - format = GL_COLOR_INDEX; - type = GL_BITMAP; + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; + read_stride = drawable->width; break; case 8: format = GL_ALPHA; @@ -300,24 +305,52 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) break; default: ErrorF("Unknown prepareaccess depth %d\n", drawable->depth); + xfree(data); return FALSE; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); glGenBuffersARB(1, &pixmap_priv->pbo); glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, stride * drawable->height, + glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, + read_stride * pixmap->drawable.height, NULL, GL_DYNAMIC_DRAW_ARB); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, stride * 8 / + glPixelStorei(GL_PACK_ROW_LENGTH, read_stride * 8 / pixmap->drawable.bitsPerPixel); glReadPixels(0, 0, pixmap->drawable.width, pixmap->drawable.height, format, type, 0); - pixmap->devPrivate.ptr = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, - GL_READ_WRITE_ARB); + read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_WRITE_ARB); + + if (pixmap->drawable.depth == 1) { + for (y = 0; y < pixmap->drawable.height; y++) { + uint8_t *read_row = read + read_stride * (pixmap->drawable.height - + y - 1); + + for (x = 0; x < pixmap->drawable.width; x++) { + int index = x / 8; + int bit = 1 << (x % 8); + + if (read_row[x]) + data[index] |= bit; + else + data[index] &= ~bit; + } + } + } else { + for (y = 0; y < pixmap->drawable.height; y++) + memcpy(data + y * stride, + read + (pixmap->drawable.height - y - 1) * stride, stride); + } + pixmap->devPrivate.ptr = data; + + glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT); + glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); + glDeleteBuffersARB(1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; return TRUE; } @@ -341,13 +374,6 @@ glamor_finish_access(DrawablePtr drawable) return; } - glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); - glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); - pixmap->devPrivate.ptr = NULL; - - stride = PixmapBytePad(drawable->width, drawable->depth); - switch (drawable->depth) { case 1: format = GL_COLOR_INDEX; @@ -370,17 +396,19 @@ glamor_finish_access(DrawablePtr drawable) return; } + stride = PixmapBytePad(drawable->width, drawable->depth); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8 / pixmap->drawable.bitsPerPixel); glRasterPos2i(0, 0); glDrawPixels(pixmap->drawable.width, pixmap->drawable.height, - format, type, 0); - glDeleteBuffersARB(1, &pixmap_priv->pbo); - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); + format, type, pixmap->devPrivate.ptr); + + xfree(pixmap->devPrivate.ptr); + pixmap->devPrivate.ptr = NULL; } void @@ -394,75 +422,6 @@ glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, glamor_solid_fail_region(pixmap, x, y, width, height); } -/** - * glamor_poly_lines() checks if it can accelerate the lines as a group of - * horizontal or vertical lines (rectangles), and uses existing rectangle fill - * acceleration if so. - */ -static void -glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, - DDXPointPtr points) -{ - 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) { - ErrorF("stub wide polylines\n"); - return; - } - if (gc->lineStyle != LineSolid || - gc->fillStyle != FillSolid) { - ErrorF("stub poly_line non-solid fill\n"); - return; - } - - rects = xalloc(sizeof(xRectangle) * (n - 1)); - x1 = points[0].x; - y1 = points[0].y; - /* If we have any non-horizontal/vertical, fall back. */ - for (i = 0; i < n - 1; i++) { - if (mode == CoordModePrevious) { - x2 = x1 + points[i + 1].x; - y2 = y1 + points[i + 1].y; - } else { - x2 = points[i + 1].x; - y2 = points[i + 1].y; - } - - if (x1 != x2 && y1 != y2) { - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - - xfree(rects); - - ErrorF("stub diagonal poly_line\n"); - glamor_solid_fail_region(pixmap, x1, y1, x2 - x1, y2 - y1); - return; - } - - if (x1 < x2) { - rects[i].x = x1; - rects[i].width = x2 - x1 + 1; - } else { - rects[i].x = x2; - rects[i].width = x1 - x2 + 1; - } - if (y1 < y2) { - rects[i].y = y1; - rects[i].height = y2 - y1 + 1; - } else { - rects[i].y = y2; - rects[i].height = y1 - y2 + 1; - } - - x1 = x2; - y1 = y2; - } - gc->ops->PolyFillRect(drawable, gc, n - 1, rects); - xfree(rects); -} - GCOps glamor_gc_ops = { .FillSpans = glamor_fill_spans, .SetSpans = glamor_set_spans, diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c new file mode 100644 index 000000000..48e62f454 --- /dev/null +++ b/glamor/glamor_polylines.c @@ -0,0 +1,107 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_polylines.c + * + * GC PolyFillRect implementation, taken straight from fb_fill.c + */ + +/** + * glamor_poly_lines() checks if it can accelerate the lines as a group of + * horizontal or vertical lines (rectangles), and uses existing rectangle fill + * acceleration if so. + */ +void +glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points) +{ + 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) { + ErrorF("stub wide polylines\n"); + return; + } + if (gc->lineStyle != LineSolid || + gc->fillStyle != FillSolid) { + ErrorF("stub poly_line non-solid fill\n"); + return; + } + + rects = xalloc(sizeof(xRectangle) * (n - 1)); + x1 = points[0].x; + y1 = points[0].y; + /* If we have any non-horizontal/vertical, fall back. */ + for (i = 0; i < n - 1; i++) { + if (mode == CoordModePrevious) { + x2 = x1 + points[i + 1].x; + y2 = y1 + points[i + 1].y; + } else { + x2 = points[i + 1].x; + y2 = points[i + 1].y; + } + + if (x1 != x2 && y1 != y2) { + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + + xfree(rects); + + ErrorF("stub diagonal poly_line\n"); + glamor_solid_fail_region(pixmap, x1, y1, x2 - x1, y2 - y1); + return; + } + + if (x1 < x2) { + rects[i].x = x1; + rects[i].width = x2 - x1 + 1; + } else { + rects[i].x = x2; + rects[i].width = x1 - x2 + 1; + } + if (y1 < y2) { + rects[i].y = y1; + rects[i].height = y2 - y1 + 1; + } else { + rects[i].y = y2; + rects[i].height = y1 - y2 + 1; + } + + x1 = x2; + y1 = y2; + } + gc->ops->PolyFillRect(drawable, gc, n - 1, rects); + xfree(rects); +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 81bb035f5..ad68c12f1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -192,6 +192,11 @@ glamor_poly_fill_rect(DrawablePtr drawable, int nrect, xRectangle *prect); +/* glamor_polylines.c */ +void +glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points); + /* glamor_putimage.c */ void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, From de675893b7ce2880289cce13be6190d55f4fc29c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 10:16:21 +0100 Subject: [PATCH 050/462] glamor: Add fallbacks for glamor_copy_area(). --- glamor/glamor_copyarea.c | 33 ++++++++++++++++++++------------- glamor/glamor_core.c | 17 +++++++++++++++-- glamor/glamor_priv.h | 12 ++++++++++++ 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index c89dffcba..077c44ffd 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -80,27 +80,22 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, RegionPtr region; if (!GLEW_EXT_framebuffer_blit) { - ErrorF("EXT_framebuffer_blit unsupported\n"); + glamor_fallback("glamor_copy_area(): " + "EXT_framebuffer_blit unsupported\n"); goto fail; } - if (!glamor_set_destination_pixmap(dst_pixmap)) { - /* - return miDoCopy(pSrcDrawable, pDstDrawable, pGC, - srcx, srcy, width, height, - dstx, dsty, fbCopyNtoN, 0, NULL); - */ - return NULL; - } + if (!glamor_set_destination_pixmap(dst_pixmap)) + goto fail; if (src_priv == NULL) { - ErrorF("glamor_copy_area: no src pixmap priv?"); + glamor_fallback("glamor_copy_area(): no src pixmap priv"); goto fail; } if (src_priv->fb == 0 && src_pixmap != screen_pixmap) { - ErrorF("glamor_copy_area: No src FBO\n"); - return NULL; + glamor_fallback("glamor_copy_area(): no src fbo"); + goto fail; } glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src_priv->fb); @@ -112,5 +107,17 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, return region; fail: - return NULL; + glamor_fallback("glamor_copy_area from %p to %p (%c,%c)\n", src, dst, + glamor_get_drawable_location(src), + glamor_get_drawable_location(dst)); + region = NULL; + if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { + region = fbCopyArea(src, dst, gc, srcx, srcy, width, height, + dstx, dsty); + glamor_finish_access(src); + } + glamor_finish_access(dst); + } + return region; } diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 4ae0d6c78..32a09b625 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -39,13 +39,26 @@ #include "glamor_priv.h" +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'; +} + Bool glamor_set_destination_pixmap(PixmapPtr pixmap) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv == NULL) { - ErrorF("no pixmap priv?"); + glamor_fallback("glamor_set_destination_pixmap(): no pixmap priv"); return FALSE; } @@ -54,7 +67,7 @@ glamor_set_destination_pixmap(PixmapPtr pixmap) PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); if (pixmap != screen_pixmap) { - ErrorF("No FBO\n"); + glamor_fallback("glamor_set_destination_pixmap(): no fbo"); return FALSE; } } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index ad68c12f1..2ee16ef56 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -117,6 +117,17 @@ glamor_pm_is_solid(DrawablePtr drawable, unsigned long planemask) FbFullMask(drawable->depth); } +static inline void +glamor_fallback(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogMessageVerb(X_INFO, 1, "glamor fallback: "); + LogVMessageVerb(X_INFO, 1, format, ap); + va_end(ap); +} + /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); @@ -129,6 +140,7 @@ Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access); void glamor_finish_access(DrawablePtr drawable); Bool glamor_prepare_access_window(WindowPtr window); void glamor_finish_access_window(WindowPtr window); +const Bool glamor_get_drawable_location(const DrawablePtr drawable); Bool glamor_create_gc(GCPtr gc); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, From e9d4794cd0bc6c8790204405fe09f968edfa409d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 11:23:14 +0100 Subject: [PATCH 051/462] glamor: Add fallbacks for Render. --- glamor/glamor_priv.h | 4 ++-- glamor/glamor_render.c | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 2ee16ef56..b470be5a4 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -123,8 +123,8 @@ glamor_fallback(char *format, ...) va_list ap; va_start(ap, format); - LogMessageVerb(X_INFO, 1, "glamor fallback: "); - LogVMessageVerb(X_INFO, 1, format, ap); + LogMessageVerb(X_INFO, 0, "fallback: "); + LogVMessageVerb(X_NONE, 0, format, ap); va_end(ap); } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 2ebb4c5c9..b6f6b86cb 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -25,7 +25,6 @@ * */ - /** @file glamor_render.c * * Render acceleration implementation @@ -35,6 +34,7 @@ #ifdef RENDER #include "mipict.h" +#include "fbpict.h" #include "glu3/glu3.h" @@ -474,11 +474,11 @@ glamor_composite(CARD8 op, source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); if (source_pixmap == dest_pixmap) { - ErrorF("source == dest\n"); + glamor_fallback("glamor_composite(): source == dest\n"); goto fail; } if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { - ErrorF("no FBO in source\n"); + glamor_fallback("glamor_composite(): no FBO in source\n"); goto fail; } } @@ -486,18 +486,19 @@ glamor_composite(CARD8 op, mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); if (mask_pixmap == dest_pixmap) { - ErrorF("mask == dest\n"); + glamor_fallback("glamor_composite(): mask == dest\n"); goto fail; } if (!mask_pixmap_priv || mask_pixmap_priv->tex == 0) { - ErrorF("no FBO in mask\n"); + glamor_fallback("glamor_composite(): no FBO in mask\n"); goto fail; } } shader = glamor_lookup_composite_shader(screen, &key); if (shader->prog == 0) { - ErrorF("No program compiled for this render accel mode\n"); + glamor_fallback("glamor_composite(): " + "no shader program for this render acccel mode\n"); goto fail; } @@ -570,9 +571,31 @@ glamor_composite(CARD8 op, return; fail: - glamor_set_composite_op(screen, PictOpSrc, dest, mask); + glamor_fallback("glamor_composite(): " + "from picts %p/%p to pict %p\n", source, mask, dest); + glUseProgramObjectARB(0); - glamor_solid_fail_region(dest_pixmap, x_dest, y_dest, width, height); + 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); + } } From 72a757ba00232fe8b42b977f5210fa119495b05e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 11:58:52 +0100 Subject: [PATCH 052/462] glamor: Use GL_MESA_pack_invert to avoid complexity in prepare_access. --- glamor/glamor_core.c | 96 +++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 32a09b625..5afbf3969 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -293,25 +293,24 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) return TRUE; } - stride = PixmapBytePad(drawable->width, drawable->depth); + stride = PixmapBytePad(pixmap->drawable.width, drawable->depth); read_stride = stride; - data = xalloc(stride * drawable->height); + data = xalloc(stride * pixmap->drawable.height); switch (drawable->depth) { case 1: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; - read_stride = drawable->width; + read_stride = pixmap->drawable.width; break; case 8: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; break; case 24: - format = GL_RGB; - type = GL_UNSIGNED_BYTE; - break; + assert(drawable->bitsPerPixel == 32); + /* FALLTHROUGH */ case 32: format = GL_BGRA; type = GL_UNSIGNED_INT_8_8_8_8_REV; @@ -323,47 +322,55 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glGenBuffersARB(1, &pixmap_priv->pbo); - glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, - read_stride * pixmap->drawable.height, - NULL, GL_DYNAMIC_DRAW_ARB); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, read_stride * 8 / pixmap->drawable.bitsPerPixel); - glReadPixels(0, 0, - pixmap->drawable.width, pixmap->drawable.height, - format, type, 0); - - read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_WRITE_ARB); - - if (pixmap->drawable.depth == 1) { - for (y = 0; y < pixmap->drawable.height; y++) { - uint8_t *read_row = read + read_stride * (pixmap->drawable.height - - y - 1); - - for (x = 0; x < pixmap->drawable.width; x++) { - int index = x / 8; - int bit = 1 << (x % 8); - - if (read_row[x]) - data[index] |= bit; - else - data[index] &= ~bit; - } - } + if (GLEW_MESA_pack_invert && drawable->depth != 1) { + glPixelStorei(GL_PACK_INVERT_MESA, 1); + glReadPixels(0, 0, + pixmap->drawable.width, pixmap->drawable.height, + format, type, data); + glPixelStorei(GL_PACK_INVERT_MESA, 0); } else { - for (y = 0; y < pixmap->drawable.height; y++) - memcpy(data + y * stride, - read + (pixmap->drawable.height - y - 1) * stride, stride); - } - pixmap->devPrivate.ptr = data; + glGenBuffersARB(1, &pixmap_priv->pbo); + glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, + read_stride * pixmap->drawable.height, + NULL, GL_DYNAMIC_DRAW_ARB); + glReadPixels(0, 0, + pixmap->drawable.width, pixmap->drawable.height, + format, type, 0); - glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT); - glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); - glDeleteBuffersARB(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; + read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_WRITE_ARB); + + if (pixmap->drawable.depth == 1) { + for (y = 0; y < pixmap->drawable.height; y++) { + uint8_t *read_row = read + + read_stride * (pixmap->drawable.height - y - 1); + + for (x = 0; x < pixmap->drawable.width; x++) { + int index = x / 8; + int bit = 1 << (x % 8); + + if (read_row[x]) + data[index] |= bit; + else + data[index] &= ~bit; + } + } + } else { + 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; } @@ -397,9 +404,8 @@ glamor_finish_access(DrawablePtr drawable) type = GL_UNSIGNED_BYTE; break; case 24: - format = GL_RGB; - type = GL_UNSIGNED_BYTE; - break; + assert(drawable->bitsPerPixel == 32); + /* FALLTHROUGH */ case 32: format = GL_BGRA; type = GL_UNSIGNED_INT_8_8_8_8_REV; @@ -409,7 +415,7 @@ glamor_finish_access(DrawablePtr drawable) return; } - stride = PixmapBytePad(drawable->width, drawable->depth); + stride = PixmapBytePad(pixmap->drawable.width, drawable->depth); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); From 55dac9b42e18dcc1586770d31ee265178e68b744 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 12:09:52 +0100 Subject: [PATCH 053/462] glamor: Add glamor_prepare_access_gc() from UXA. --- glamor/glamor_core.c | 36 ++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 5afbf3969..431cb4139 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -429,6 +429,42 @@ glamor_finish_access(DrawablePtr drawable) xfree(pixmap->devPrivate.ptr); pixmap->devPrivate.ptr = NULL; } +/** + * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the + * current fill style. + * + * Solid doesn't use an extra pixmap source, so we don't worry about them. + * Stippled/OpaqueStippled are 1bpp and can be in fb, so we should worry + * about them. + */ +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; + } + } + return TRUE; +} + +/** + * Finishes access to the tile in the GC, if used. + */ +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); +} void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b470be5a4..2045ed691 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -140,6 +140,8 @@ Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access); void glamor_finish_access(DrawablePtr drawable); Bool glamor_prepare_access_window(WindowPtr window); void glamor_finish_access_window(WindowPtr window); +Bool glamor_prepare_access_gc(GCPtr gc); +void glamor_finish_access_gc(GCPtr gc); const Bool glamor_get_drawable_location(const DrawablePtr drawable); Bool glamor_create_gc(GCPtr gc); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, From 22cad98975091ed724a37ec940946cd2899ebcbf Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 12:13:15 +0100 Subject: [PATCH 054/462] glamor: Add fallback support to glamor_set_spans(). --- glamor/glamor_setspans.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 66ec3dafd..0bd0ac1c2 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -68,8 +68,9 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, type = GL_UNSIGNED_INT_8_8_8_8_REV; break; default: - ErrorF("Unknown setspans depth %d\n", drawable->depth); - return; + glamor_fallback("glamor_set_spans()Unknown depth %d\n", + drawable->depth); + goto fail; } if (!glamor_set_destination_pixmap(dest_pixmap)) @@ -117,4 +118,11 @@ fail: glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(GXcopy); xfree(temp_src); + + glamor_fallback("glamor_set_spans(): 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); + glamor_finish_access(drawable); + } } From 0e56c182c3b06f5b02d357e2b8e930a580bd0274 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 12:16:30 +0100 Subject: [PATCH 055/462] glamor: Add fallback support to glamor_put_image(). --- glamor/glamor_putimage.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 55854daae..39f120eca 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -224,7 +224,13 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, fail: glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); - glamor_solid_fail_region(pixmap, x, y, w, h); + + glamor_fallback("glamor_put_image(): to %p (%c)\n", + drawable, glamor_get_drawable_location(drawable)); + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { + fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); + glamor_finish_access(drawable); + } } void @@ -331,5 +337,11 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, fail: glamor_set_planemask(pixmap, ~0); - glamor_solid_fail_region(pixmap, x, y, w, h); + glamor_fallback("glamor_put_image(): 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, + bits); + glamor_finish_access(drawable); + } } From e93070affdf64c47be02684e7902a61e7ae9fa33 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 12:44:03 +0100 Subject: [PATCH 056/462] glamor: Fix up the access flags for glamor_prepare_access(). --- glamor/glamor_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 431cb4139..b0653d8cb 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -337,12 +337,12 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, read_stride * pixmap->drawable.height, - NULL, GL_DYNAMIC_DRAW_ARB); + NULL, GL_STREAM_READ_ARB); glReadPixels(0, 0, pixmap->drawable.width, pixmap->drawable.height, format, type, 0); - read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_WRITE_ARB); + read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB); if (pixmap->drawable.depth == 1) { for (y = 0; y < pixmap->drawable.height; y++) { From b5087ff9b1e5495c742e581f586c055de878dd4b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 12:47:59 +0100 Subject: [PATCH 057/462] glamor: Fix the row length of 1bpp prepare_access. --- glamor/glamor_core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index b0653d8cb..9d0e40f44 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -323,9 +323,12 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, read_stride * 8 / - pixmap->drawable.bitsPerPixel); - + if (drawable->depth != 1) { + glPixelStorei(GL_PACK_ROW_LENGTH, read_stride * 8 / + pixmap->drawable.bitsPerPixel); + } else { + glPixelStorei(GL_PACK_ROW_LENGTH, read_stride); + } if (GLEW_MESA_pack_invert && drawable->depth != 1) { glPixelStorei(GL_PACK_INVERT_MESA, 1); glReadPixels(0, 0, From ec526eab8f02e0bcce859a1b7ebaf6c5bccc5e87 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 13:05:13 +0100 Subject: [PATCH 058/462] ephyr: Hook the glamor into damage and draw into the backbuffer. This should avoid a bunch of absurdity with GLX front buffer handling, fix exposes, and improve performance. For now we're copying the whole buffer while glamor is developed. --- hw/kdrive/ephyr/ephyr.c | 3 --- hw/kdrive/ephyr/ephyr.h | 1 + hw/kdrive/ephyr/hostx.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 16959d74b..1aacc5fe8 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -395,9 +395,6 @@ ephyrSetInternalDamage (ScreenPtr pScreen) EphyrScrPriv *scrpriv = screen->driver; PixmapPtr pPixmap = NULL; - if (ephyrFuncs.initAccel == ephyr_glamor_init) - return TRUE; - scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0, (DamageDestroyFunc) 0, DamageReportNone, diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index cd1521209..9dcde8d56 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -201,6 +201,7 @@ Bool ephyr_glamor_init(ScreenPtr pScreen); void ephyr_glamor_enable(ScreenPtr pScreen); void ephyr_glamor_disable(ScreenPtr pScreen); void ephyr_glamor_fini(ScreenPtr pScreen); +void ephyr_glamor_host_paint_rect(ScreenPtr pScreen); /*ephyvideo.c*/ diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index c7c792984..15dfc70ae 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -767,6 +767,11 @@ hostx_screen_init (EphyrScreenInfo screen, static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, int x, int y, int width, int height); +static void +ephyr_glamor_paint_rect (EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, + int width, int height); void hostx_paint_rect (EphyrScreenInfo screen, @@ -778,6 +783,11 @@ hostx_paint_rect (EphyrScreenInfo screen, EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ; + if (ephyr_glamor) { + ephyr_glamor_paint_rect(screen, sx, sy, dx, dy, width, height); + return; + } + /* * Copy the image data updated by the shadow layer * on to the window @@ -1464,6 +1474,7 @@ ephyr_glamor_get_visual(void) GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, 1, None}; XVisualInfo *visual_info; int event_base = 0, error_base = 0; @@ -1495,3 +1506,29 @@ ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) if (!glXMakeCurrent(dpy, host_screen->win, ctx)) errx(1, "glXMakeCurrent failed\n"); } + +static void +ephyr_glamor_paint_rect (EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, + int width, int height) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + static PFNGLXCOPYSUBBUFFERMESAPROC pglXCopySubBufferMESA = NULL; + + if (!pglXCopySubBufferMESA) { + pglXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC) + glXGetProcAddressARB((const GLubyte*)"glXCopySubBufferMESA"); + assert(pglXCopySubBufferMESA); + } + + /* Always copy the full screen until we get things rendering correctly. */ +#if 0 + pglXCopySubBufferMESA(HostX.dpy, host_screen->win, + sx, sy, width, height); +#else + pglXCopySubBufferMESA(HostX.dpy, host_screen->win, + 0, 0, + host_screen->win_width, host_screen->win_height); +#endif +} From 6ce378f11ff396f350cbaa280086f6f9600da29e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 13:15:38 +0100 Subject: [PATCH 059/462] glamor: Add fallback support for glamor_get_spans(). --- glamor/glamor_getspans.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 76c6cceef..8339eb130 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -76,14 +76,13 @@ glamor_get_spans(DrawablePtr drawable, type = GL_UNSIGNED_INT_8_8_8_8_REV; break; default: - ErrorF("Unknown getspans depth %d\n", drawable->depth); - return; + glamor_fallback("glamor_get_spans(): " + "Unknown getspans depth %d\n", drawable->depth); + goto fail; } - if (!glamor_set_destination_pixmap(pixmap)) { - fbGetSpans(drawable, wmax, points, widths, count, dst); - return; - } + if (!glamor_set_destination_pixmap(pixmap)) + goto fail; for (i = 0; i < count; i++) { glReadPixels(points[i].x - pixmap->screen_x, @@ -102,4 +101,14 @@ glamor_get_spans(DrawablePtr drawable, } } xfree(temp_dst); + return; + +fail: + free(temp_dst); + glamor_fallback("glamor_get_spans() 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); + glamor_finish_access(drawable); + } } From 745502af962a2bb475c0c667c3091c2c080771dc Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 13:27:47 +0100 Subject: [PATCH 060/462] glamor: Add check for EXT_bgra which we rely on. --- glamor/glamor.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 507a19be4..a2cd02a6a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -181,6 +181,10 @@ glamor_init(ScreenPtr screen) ErrorF("GL_ARB_pixel_buffer_object required\n"); goto fail; } + if (!GLEW_EXT_bgra) { + ErrorF("GL_EXT_bgra required\n"); + goto fail; + } if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, From d8d3fa10346302384b8e62967c5a67893ed1c67b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 14:53:41 +0100 Subject: [PATCH 061/462] glamor: All the fallbacks in the world. Bringup is really not flying when I can't see anything. So dump back to all software so I can turn on a bit at a time. --- glamor/glamor_copyarea.c | 2 ++ glamor/glamor_fill.c | 2 ++ glamor/glamor_fillspans.c | 13 +++++++++++++ glamor/glamor_getspans.c | 2 ++ glamor/glamor_polyfillrect.c | 15 +++++++++++++++ glamor/glamor_putimage.c | 2 ++ glamor/glamor_render.c | 2 ++ glamor/glamor_setspans.c | 2 ++ 8 files changed, 40 insertions(+) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 077c44ffd..b0f6a7e2f 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -79,6 +79,8 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); RegionPtr region; + goto fail; + if (!GLEW_EXT_framebuffer_blit) { glamor_fallback("glamor_copy_area(): " "EXT_framebuffer_blit unsupported\n"); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 6290f1210..b3418a91d 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -42,6 +42,8 @@ glamor_fill(DrawablePtr drawable, { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); + assert(0); + switch (gc->fillStyle) { case FillSolid: glamor_solid(dst_pixmap, diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 120e3467d..9b070eced 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -45,6 +45,8 @@ glamor_fill_spans(DrawablePtr drawable, int fullX1, fullX2, fullY1; int partX1, partX2; + goto fail; + extents = REGION_EXTENTS(gc->pScreen, clip); extentX1 = extents->x1; extentY1 = extents->y1; @@ -97,4 +99,15 @@ glamor_fill_spans(DrawablePtr drawable, } } } + return; +fail: + 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)) { + fbFillSpans(drawable, gc, n, points, widths, sorted); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); + } } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 8339eb130..6e92b4d0b 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -56,6 +56,8 @@ glamor_get_spans(DrawablePtr drawable, int i, j; uint8_t *temp_dst = NULL, *readpixels_dst = (uint8_t *)dst; + goto fail; + switch (drawable->depth) { case 1: temp_dst = xalloc(wmax); diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index ae8963dac..dc3c0e69a 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -52,6 +52,8 @@ glamor_poly_fill_rect(DrawablePtr drawable, int xorg, yorg; int n; + goto fail; + xorg = drawable->x; yorg = drawable->y; @@ -115,4 +117,17 @@ glamor_poly_fill_rect(DrawablePtr drawable, } } } + return; + +fail: + glamor_fallback("glamor_poly_fill_rect() 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 ); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); + } } diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 39f120eca..537992101 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -245,6 +245,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int bpp = drawable->bitsPerPixel; int src_stride = PixmapBytePad(w, drawable->depth); + goto fail; + if (!glamor_set_destination_pixmap(pixmap)) { fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b6f6b86cb..f9e7341c1 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -424,6 +424,8 @@ glamor_composite(CARD8 op, RegionRec region; int i; + goto fail; + /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. */ diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 0bd0ac1c2..32f7bc515 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -43,6 +43,8 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; + goto fail; + for (i = 0 ; i < n; i++) { if (wmax < widths[i]) wmax = widths[i]; From 45de3d24b44aa3feabdda0e377d637f498e03eb0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 14:40:06 +0100 Subject: [PATCH 062/462] glamor: Replace the glDrawPixels in glamor_finish_access with GLSL. Root weave displays. \o/ --- glamor/glamor.c | 1 + glamor/glamor_core.c | 88 +++++++++++++++++++++++++++++++++++++++++++- glamor/glamor_priv.h | 4 ++ 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index a2cd02a6a..ba16d63fc 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -224,6 +224,7 @@ glamor_init(ScreenPtr screen) glamor_init_tile_shader(screen); glamor_init_putimage_shaders(screen); glamor_init_composite_shaders(screen); + glamor_init_finish_access_shaders(screen); return TRUE; diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 9d0e40f44..f35baafa0 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -378,13 +378,67 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) return TRUE; } +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"; + GLint fs_prog, vs_prog; + + glamor_priv->finish_access_prog = 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); + } else { + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, vs_source); + glAttachObjectARB(glamor_priv->finish_access_prog, vs_prog); + } + + glamor_link_glsl_prog(glamor_priv->finish_access_prog); + + 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); + } +} + 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); unsigned int stride; GLenum format, type; + static float vertices[4][2] = {{-1, -1}, + { 1, -1}, + { 1, 1}, + {-1, 1}}; + static float texcoords[4][2] = {{0, 1}, + {1, 1}, + {1, 0}, + {0, 0}}; + GLuint tex; if (pixmap_priv == NULL) return; @@ -397,6 +451,10 @@ glamor_finish_access(DrawablePtr drawable) return; } + /* Check if finish_access was already called once on this */ + if (pixmap->devPrivate.ptr == NULL) + return; + switch (drawable->depth) { case 1: format = GL_COLOR_INDEX; @@ -420,18 +478,44 @@ glamor_finish_access(DrawablePtr drawable) stride = PixmapBytePad(pixmap->drawable.width, drawable->depth); + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + + glClientActiveTexture(GL_TEXTURE0); + 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); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8 / pixmap->drawable.bitsPerPixel); - glRasterPos2i(0, 0); - glDrawPixels(pixmap->drawable.width, pixmap->drawable.height, + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + pixmap->drawable.width, pixmap->drawable.height, 0, format, type, pixmap->devPrivate.ptr); + 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); + glUseProgramObjectARB(glamor_priv->finish_access_prog); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisable(GL_TEXTURE_2D); + glUseProgramObjectARB(0); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDeleteTextures(1, &tex); xfree(pixmap->devPrivate.ptr); pixmap->devPrivate.ptr = NULL; } + /** * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the * current fill style. diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 2045ed691..dc3b77860 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -63,6 +63,9 @@ typedef struct glamor_screen_private { ChangeWindowAttributesProcPtr saved_change_window_attributes; BitmapToRegionProcPtr saved_bitmap_to_region; + /* glamor_finishaccess */ + GLint finish_access_prog; + /* glamor_solid */ GLint solid_prog; GLint solid_color_uniform_location; @@ -142,6 +145,7 @@ Bool glamor_prepare_access_window(WindowPtr window); void glamor_finish_access_window(WindowPtr window); Bool glamor_prepare_access_gc(GCPtr gc); void glamor_finish_access_gc(GCPtr gc); +void glamor_init_finish_access_shaders(ScreenPtr screen); const Bool glamor_get_drawable_location(const DrawablePtr drawable); Bool glamor_create_gc(GCPtr gc); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, From c3c3a6349766b4fdee080ff203fb548725e42e50 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 15:34:45 +0100 Subject: [PATCH 063/462] glamor: Use the pixmap stride in fallbacks instead of trying to guess it. Mostly fixes gnome-terminal text. --- glamor/glamor_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f35baafa0..4d03bd718 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -293,7 +293,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) return TRUE; } - stride = PixmapBytePad(pixmap->drawable.width, drawable->depth); + stride = pixmap->devKind; read_stride = stride; data = xalloc(stride * pixmap->drawable.height); @@ -476,7 +476,7 @@ glamor_finish_access(DrawablePtr drawable) return; } - stride = PixmapBytePad(pixmap->drawable.width, drawable->depth); + stride = pixmap->devKind; glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); From 5332547a0ac6ae6b9f1a6c6428e6fdbdf303108f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 17:14:34 +0100 Subject: [PATCH 064/462] glamor: Fix prepare_access on 1bpp data. Apparently I don't have anything hitting this path, so I'm not sure if it's good or not. --- glamor/glamor_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 4d03bd718..4ec8540f0 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -351,15 +351,16 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) for (y = 0; y < pixmap->drawable.height; y++) { uint8_t *read_row = read + read_stride * (pixmap->drawable.height - y - 1); + uint8_t *write_row = data + y * stride; for (x = 0; x < pixmap->drawable.width; x++) { int index = x / 8; int bit = 1 << (x % 8); if (read_row[x]) - data[index] |= bit; + write_row[index] |= bit; else - data[index] &= ~bit; + write_row[index] &= ~bit; } } } else { From 95d4a5a6ab58625d8205461157263bfb635ccd1a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 19:38:00 +0100 Subject: [PATCH 065/462] glamor: Enable fill acceleration and flip opposite for pixmaps too. Here's my theory for the flipping: It doesn't really matter which orientation we store the pixmaps if we don't scan them out. We have to flip coordinates for the window system framebuffer. Doing so for everything else makes things consistent. I'm not sure how this will interact with future GLX integration, though. --- glamor/glamor_core.c | 7 +------ glamor/glamor_fill.c | 2 -- glamor/glamor_polyfillrect.c | 3 ++- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 4ec8540f0..ca7add4ac 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -177,12 +177,7 @@ glamor_set_transform_for_pixmap(PixmapPtr pixmap, 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); - if (pixmap == screen_pixmap) - glUniform1fARB(uniform_locations->y_scale, - -2.0f / pixmap->drawable.height); - else - glUniform1fARB(uniform_locations->y_scale, - 2.0f / pixmap->drawable.height); + glUniform1fARB(uniform_locations->y_scale, -2.0f / pixmap->drawable.height); } GLint diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index b3418a91d..6290f1210 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -42,8 +42,6 @@ glamor_fill(DrawablePtr drawable, { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); - assert(0); - switch (gc->fillStyle) { case FillSolid: glamor_solid(dst_pixmap, diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index dc3c0e69a..62e0a0fe4 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -52,7 +52,8 @@ glamor_poly_fill_rect(DrawablePtr drawable, int xorg, yorg; int n; - goto fail; + if (gc->fillStyle != FillSolid) + goto fail; xorg = drawable->x; yorg = drawable->y; From 647b9fb49a5bb636c9b0da6b708083328238543a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 20:12:44 +0100 Subject: [PATCH 066/462] glamor: Add CopyWindow implementation so it doesn't crash. --- glamor/Makefile.am | 1 + glamor/glamor.c | 4 +++ glamor/glamor_copyarea.c | 18 ++++++++++-- glamor/glamor_copywindow.c | 60 ++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 18 ++++++++++++ 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 glamor/glamor_copywindow.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index ce7869244..17139c09f 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -18,6 +18,7 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ glamor_copyarea.c \ + glamor_copywindow.c \ glamor_core.c \ glamor_fill.c \ glamor_fillspans.c \ diff --git a/glamor/glamor.c b/glamor/glamor.c index ba16d63fc..7bb093474 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -210,6 +210,9 @@ glamor_init(ScreenPtr screen) glamor_priv->saved_change_window_attributes = screen->ChangeWindowAttributes; screen->ChangeWindowAttributes = glamor_change_window_attributes; + glamor_priv->saved_copy_window = screen->CopyWindow; + screen->CopyWindow = glamor_copy_window; + glamor_priv->saved_bitmap_to_region = screen->BitmapToRegion; screen->BitmapToRegion = glamor_bitmap_to_region; @@ -247,6 +250,7 @@ glamor_fini(ScreenPtr screen) screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; screen->GetSpans = glamor_priv->saved_get_spans; screen->ChangeWindowAttributes = glamor_priv->saved_change_window_attributes; + screen->CopyWindow = glamor_priv->saved_copy_window; screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; #ifdef RENDER ps->Composite = glamor_priv->saved_composite; diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index b0f6a7e2f..7f14f2a4c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -32,7 +32,7 @@ * GC CopyArea implementation */ -static void +void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, @@ -49,6 +49,8 @@ glamor_copy_n_to_n(DrawablePtr src, PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int i; + goto fail; + glamor_set_alu(gc->alu); if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fail; @@ -64,6 +66,18 @@ glamor_copy_n_to_n(DrawablePtr src, } fail: + 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)) { + if (glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { + fbCopyNtoN(src, dst, gc, box, nbox, + dx, dy, reverse, upsidedown, bitplane, + closure); + glamor_finish_access(src); + } + glamor_finish_access(dst); + } glamor_set_alu(GXcopy); glamor_set_planemask(dst_pixmap, ~0); } @@ -79,8 +93,6 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); RegionPtr region; - goto fail; - if (!GLEW_EXT_framebuffer_blit) { glamor_fallback("glamor_copy_area(): " "EXT_framebuffer_blit unsupported\n"); diff --git a/glamor/glamor_copywindow.c b/glamor/glamor_copywindow.c new file mode 100644 index 000000000..1e840a934 --- /dev/null +++ b/glamor/glamor_copywindow.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2008 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_copywindow.c + * + * Screen CopyWindow implementation. + */ + +void glamor_copy_window(WindowPtr win, DDXPointRec old_origin, + RegionPtr src_region) +{ + RegionRec dst_region; + int dx, dy; + PixmapPtr pixmap = win->drawable.pScreen->GetWindowPixmap(win); + + dx = old_origin.x - win->drawable.x; + dy = old_origin.y - win->drawable.y; + REGION_TRANSLATE(win->drawable.pScreen, src_region, -dx, -dy); + + REGION_INIT(win->drawable.pScreen, &dst_region, NullBox, 0); + + REGION_INTERSECT(win->drawable.pScreen, &dst_region, &win->borderClip, + src_region); +#ifdef COMPOSITE + if (pixmap->screen_x || pixmap->screen_y) + REGION_TRANSLATE(win->drawable.pScreen, &dst_region, + -pixmap->screen_x, -pixmap->screen_y); +#endif + + miCopyRegion(&pixmap->drawable, &pixmap->drawable, + NULL, &dst_region, dx, dy, glamor_copy_n_to_n, 0, NULL); + + REGION_UNINIT(win->drawable.pScreen, &dst_region); +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index dc3b77860..adc6997cc 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -61,6 +61,7 @@ typedef struct glamor_screen_private { CompositeProcPtr saved_composite; TrapezoidsProcPtr saved_trapezoids; ChangeWindowAttributesProcPtr saved_change_window_attributes; + CopyWindowProcPtr saved_copy_window; BitmapToRegionProcPtr saved_bitmap_to_region; /* glamor_finishaccess */ @@ -138,6 +139,23 @@ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, int srcx, int srcy, int width, int height, int dstx, int dsty); +void +glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +/* glamor_copywindow.c */ +void glamor_copy_window(WindowPtr win, DDXPointRec old_origin, + RegionPtr src_region); + /* glamor_core.c */ Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access); void glamor_finish_access(DrawablePtr drawable); From 35847c578e9c35a3c90da792c34c1cb0cc536261 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 21:24:15 +0100 Subject: [PATCH 067/462] glamor: Add acceleration for copyarea not from the screen. --- glamor/glamor_copyarea.c | 119 ++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 26 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 7f14f2a4c..e07cf6224 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -32,6 +32,30 @@ * GC CopyArea implementation */ +static float +v_from_x_coord_x(PixmapPtr pixmap, int x) +{ + return (float)(x - pixmap->screen_x) / pixmap->drawable.width * 2.0 - 1.0; +} + +static float +v_from_x_coord_y(PixmapPtr pixmap, int y) +{ + return (float)(y - pixmap->screen_y) / pixmap->drawable.height * -2.0 + 1.0; +} + +static float +t_from_x_coord_x(PixmapPtr pixmap, int x) +{ + return (float)(x - pixmap->screen_x) / pixmap->drawable.width; +} + +static float +t_from_x_coord_y(PixmapPtr pixmap, int y) +{ + return 1.0 - (float)(y - pixmap->screen_y) / pixmap->drawable.height; +} + void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, @@ -45,16 +69,78 @@ glamor_copy_n_to_n(DrawablePtr src, Pixel bitplane, void *closure) { + glamor_screen_private *glamor_priv = + glamor_get_screen_private(dst->pScreen); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int i; + float vertices[4][2], texcoords[4][2]; + glamor_pixmap_private *src_pixmap_priv; - goto fail; + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - glamor_set_alu(gc->alu); - if (!glamor_set_planemask(dst_pixmap, gc->planemask)) + if (src == dst) { + glamor_fallback("glamor_copy_n_to_n with 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_set_destination_pixmap(dst_pixmap)) goto fail; + if (gc) { + glamor_set_alu(gc->alu); + if (!glamor_set_planemask(dst_pixmap, gc->planemask)) + goto fail; + } + + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + assert(GLEW_ARB_fragment_shader); + glUseProgramObjectARB(glamor_priv->finish_access_prog); + + for (i = 0; i < nbox; i++) { + vertices[0][0] = v_from_x_coord_x(dst_pixmap, box[i].x1); + vertices[0][1] = v_from_x_coord_y(dst_pixmap, box[i].y1); + vertices[1][0] = v_from_x_coord_x(dst_pixmap, box[i].x2); + vertices[1][1] = v_from_x_coord_y(dst_pixmap, box[i].y1); + vertices[2][0] = v_from_x_coord_x(dst_pixmap, box[i].x2); + vertices[2][1] = v_from_x_coord_y(dst_pixmap, box[i].y2); + vertices[3][0] = v_from_x_coord_x(dst_pixmap, box[i].x1); + vertices[3][1] = v_from_x_coord_y(dst_pixmap, box[i].y2); + + texcoords[0][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); + texcoords[0][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); + texcoords[1][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); + texcoords[1][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); + texcoords[2][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); + texcoords[2][1] = t_from_x_coord_y(src_pixmap, box[i].y2 + dy); + texcoords[3][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); + texcoords[3][1] = t_from_x_coord_y(src_pixmap, box[i].y2 + dy); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } + + glUseProgramObjectARB(0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + +#if 0 for (i = 0; i < nbox; i++) { glRasterPos2i(box[i].x1 - dst_pixmap->screen_x, box[i].y1 - dst_pixmap->screen_y); @@ -64,9 +150,12 @@ glamor_copy_n_to_n(DrawablePtr src, box[i].y2 - box[i].y1, GL_COLOR); } +#endif + + return; fail: - glamor_fallback("from %p to %p (%c,%c)\n", src, dst, + glamor_fallback("glamor_copy_area() 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)) { @@ -89,31 +178,9 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, ScreenPtr screen = dst->pScreen; PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); RegionPtr region; - if (!GLEW_EXT_framebuffer_blit) { - glamor_fallback("glamor_copy_area(): " - "EXT_framebuffer_blit unsupported\n"); - goto fail; - } - - if (!glamor_set_destination_pixmap(dst_pixmap)) - goto fail; - - if (src_priv == NULL) { - glamor_fallback("glamor_copy_area(): no src pixmap priv"); - goto fail; - } - - if (src_priv->fb == 0 && src_pixmap != screen_pixmap) { - glamor_fallback("glamor_copy_area(): no src fbo"); - goto fail; - } - - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src_priv->fb); - region = miDoCopy(src, dst, gc, srcx, srcy, width, height, dstx, dsty, glamor_copy_n_to_n, 0, NULL); From 4811e428a9206ef59487fb0d3fab160a19845d46 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 21:46:49 +0100 Subject: [PATCH 068/462] glamor: Pull in UXA code for dumping some composites down to copy_n_to_n. Window dragging with metacity+gnome-terminal+xcompmgr is almost credible. --- glamor/glamor_render.c | 57 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f9e7341c1..a7777fbad 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -399,6 +399,32 @@ glamor_set_composite_solid(PicturePtr picture, GLint uniform_location) 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 (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 != dst->format) + return 0; + + if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8) + return 1; + } + + return 0; +} + void glamor_composite(CARD8 op, PicturePtr source, @@ -424,8 +450,6 @@ glamor_composite(CARD8 op, RegionRec region; int i; - goto fail; - /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. */ @@ -445,6 +469,35 @@ glamor_composite(CARD8 op, return; } + if (!mask) { + if (compatible_formats (op, dest, source)) { + if (!source->repeat && !source->transform) { + 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; + + 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; + } + } + } + + goto fail; + memset(&key, 0, sizeof(key)); key.has_mask = (mask != NULL); if (!source->pDrawable) { From ad67299fa2afc8b42432d71d14163a36e013fef7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 21:52:35 +0100 Subject: [PATCH 069/462] glamor: Provide more information about the operands to fallback composites. --- glamor/glamor_render.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index a7777fbad..495f5683f 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -425,6 +425,27 @@ compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) return 0; } +static char +glamor_get_picture_location(PicturePtr picture) +{ + 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 '?'; + } + } + return glamor_get_drawable_location(picture->pDrawable); +} + void glamor_composite(CARD8 op, PicturePtr source, @@ -627,7 +648,12 @@ glamor_composite(CARD8 op, fail: glamor_fallback("glamor_composite(): " - "from picts %p/%p to pict %p\n", source, mask, dest); + "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); if (glamor_prepare_access(dest->pDrawable, GLAMOR_ACCESS_RW)) { From 15e58b5ffb427c6c6f5172ccd72758047b98024a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 8 Feb 2010 22:05:51 +0100 Subject: [PATCH 070/462] glamor: Split the copy path out into its own function. --- glamor/glamor_render.c | 72 ++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 495f5683f..ba67d7381 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -446,6 +446,49 @@ glamor_get_picture_location(PicturePtr picture) return glamor_get_drawable_location(picture->pDrawable); } +static Bool +glamor_composite_copy(CARD8 op, + PicturePtr source, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_dest, + INT16 y_dest, + CARD16 width, + CARD16 height) +{ + RegionRec region; + + if (!compatible_formats(op, dest, source)) + 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; + + 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; +} + void glamor_composite(CARD8 op, PicturePtr source, @@ -491,30 +534,11 @@ glamor_composite(CARD8 op, } if (!mask) { - if (compatible_formats (op, dest, source)) { - if (!source->repeat && !source->transform) { - 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; - - 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; - } - } + if (glamor_composite_copy(op, source, dest, + x_source, y_source, + x_dest, y_dest, + width, height)) + return; } goto fail; From 4f398b29dd42260d2c02e8e795546fd0623397b1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 21:56:39 -0600 Subject: [PATCH 071/462] glamor: Align stride of fallback pixmap data to 32 bits. fb/pixman demand this alignment, and all sorts of things go badly otherwise. Fixes piglit x11-8bpp-7x8-draw. --- glamor/glamor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 7bb093474..7bc75aa13 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -112,7 +112,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, 0); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, - (w * pixmap->drawable.bitsPerPixel + 7) / 8, + (((w * pixmap->drawable.bitsPerPixel + + 7) / 8) + 3) & ~3, NULL); return pixmap; From d8c2662bf452a82c8fcbdd1c95a40ee34d2c32ca Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 22:48:28 -0600 Subject: [PATCH 072/462] glamor: Set active texture in finishaccess drawing. --- glamor/glamor_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index ca7add4ac..b0a64f2ef 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -171,9 +171,6 @@ void glamor_set_transform_for_pixmap(PixmapPtr pixmap, glamor_transform_uniforms *uniform_locations) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - 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); @@ -489,6 +486,7 @@ glamor_finish_access(DrawablePtr drawable) pixmap->drawable.bitsPerPixel); glGenTextures(1, &tex); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixmap->drawable.width, pixmap->drawable.height, 0, From a0b589e90a885cf20b349b95df31bb0823a1514b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 22:49:27 -0600 Subject: [PATCH 073/462] glamor: Restore planemask to all-on when finishing a fill. --- glamor/glamor_fill.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 6290f1210..1b601ee5d 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -172,6 +172,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glUseProgramObjectARB(0); fail: glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); } /* Highlight places where we're doing it wrong. */ From 7e6432e7b94f7f99b257da8de53573108d30ae22 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 22:54:40 -0600 Subject: [PATCH 074/462] glamor: Fix up and enable accelerated composite. --- glamor/glamor_copyarea.c | 28 +-- glamor/glamor_priv.h | 24 +++ glamor/glamor_render.c | 360 ++++++++++++++++++++++++--------------- 3 files changed, 249 insertions(+), 163 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index e07cf6224..695edc3e9 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -32,30 +32,6 @@ * GC CopyArea implementation */ -static float -v_from_x_coord_x(PixmapPtr pixmap, int x) -{ - return (float)(x - pixmap->screen_x) / pixmap->drawable.width * 2.0 - 1.0; -} - -static float -v_from_x_coord_y(PixmapPtr pixmap, int y) -{ - return (float)(y - pixmap->screen_y) / pixmap->drawable.height * -2.0 + 1.0; -} - -static float -t_from_x_coord_x(PixmapPtr pixmap, int x) -{ - return (float)(x - pixmap->screen_x) / pixmap->drawable.width; -} - -static float -t_from_x_coord_y(PixmapPtr pixmap, int y) -{ - return 1.0 - (float)(y - pixmap->screen_y) / pixmap->drawable.height; -} - void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, @@ -175,10 +151,12 @@ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, int srcx, int srcy, int width, int height, int dstx, int dsty) { +#if 0 ScreenPtr screen = dst->pScreen; PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); +#endif RegionPtr region; region = miDoCopy(src, dst, gc, @@ -187,6 +165,7 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, return region; +#if 0 fail: glamor_fallback("glamor_copy_area from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), @@ -201,4 +180,5 @@ fail: glamor_finish_access(dst); } return region; +#endif } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index adc6997cc..526b2cf3a 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -132,6 +132,30 @@ glamor_fallback(char *format, ...) va_end(ap); } +static inline float +v_from_x_coord_x(PixmapPtr pixmap, int x) +{ + return (float)(x - pixmap->screen_x) / pixmap->drawable.width * 2.0 - 1.0; +} + +static inline float +v_from_x_coord_y(PixmapPtr pixmap, int y) +{ + return (float)(y - pixmap->screen_y) / pixmap->drawable.height * -2.0 + 1.0; +} + +static inline float +t_from_x_coord_x(PixmapPtr pixmap, int x) +{ + return (float)(x - pixmap->screen_x) / pixmap->drawable.width; +} + +static inline float +t_from_x_coord_y(PixmapPtr pixmap, int y) +{ + return 1.0 - (float)(y - pixmap->screen_y) / pixmap->drawable.height; +} + /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index ba67d7381..be28bd4e0 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -94,23 +94,20 @@ static GLuint glamor_create_composite_fs(struct shader_key *key) { const char *source_pixmap_header = - "uniform sampler2D source_sampler;\n" - "varying vec4 source_coords;\n"; + "uniform sampler2D source_sampler;\n"; const char *source_solid_header = "uniform vec4 source;\n"; const char *mask_pixmap_header = - "uniform sampler2D mask_sampler;\n" - "varying vec4 mask_coords;\n"; + "uniform sampler2D mask_sampler;\n"; const char *mask_solid_header = "uniform vec4 mask;\n"; const char *main_opening = "void main()\n" "{\n"; const char *source_pixmap_fetch = - " vec4 source = texture2DProj(source_sampler, " - " source_coords.xyw);\n"; + " vec4 source = texture2D(source_sampler, gl_TexCoord[0].xy);\n"; const char *mask_pixmap_fetch = - " vec4 mask = texture2DProj(mask_sampler, mask_coords.xyw);\n"; + " vec4 mask = texture2D(mask_sampler, gl_TexCoord[1].xy);\n"; const char *source_in_mask = " gl_FragColor = source * mask.w;\n"; const char *source_only = @@ -156,30 +153,20 @@ glamor_create_composite_fs(struct shader_key *key) static GLuint glamor_create_composite_vs(struct shader_key *key) { - const char *header = - "uniform mat4 dest_to_dest;\n" - "uniform mat4 dest_to_source;\n" - "varying vec4 source_coords;\n"; - const char *mask_header = - "uniform mat4 dest_to_mask;\n" - "varying vec4 mask_coords;\n"; const char *main_opening = "void main()\n" "{\n" - " vec4 incoming_dest_coords = vec4(gl_Vertex.xy, 0, 1);\n" - " gl_Position = dest_to_dest * incoming_dest_coords;\n" - " source_coords = dest_to_source * incoming_dest_coords;\n"; + " gl_Position = gl_Vertex;\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n"; const char *mask_coords = - " mask_coords = dest_to_mask * incoming_dest_coords;\n"; + " gl_TexCoord[1] = gl_MultiTexCoord1;\n"; const char *main_closing = "}\n"; char *source; GLuint prog; Bool compute_mask_coords = key->has_mask && !key->solid_mask; - source = XNFprintf("%s%s%s%s%s", - header, - compute_mask_coords ? mask_header : "", + source = XNFprintf("%s%s%s", main_opening, compute_mask_coords ? mask_coords : "", main_closing); @@ -214,8 +201,6 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) shader->prog = prog; glUseProgramObjectARB(prog); - shader->dest_to_dest_uniform_location = - glGetUniformLocationARB(prog, "dest_to_dest"); if (key->solid_source) { shader->source_uniform_location = glGetUniformLocationARB(prog, @@ -223,8 +208,6 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) } else { source_sampler_uniform_location = glGetUniformLocationARB(prog, "source_sampler"); - shader->dest_to_source_uniform_location = - glGetUniformLocationARB(prog, "dest_to_source"); glUniform1i(source_sampler_uniform_location, 0); } @@ -236,8 +219,6 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) mask_sampler_uniform_location = glGetUniformLocationARB(prog, "mask_sampler"); glUniform1i(mask_sampler_uniform_location, 1); - shader->dest_to_mask_uniform_location = - glGetUniformLocationARB(prog, "dest_to_mask"); } } } @@ -255,6 +236,7 @@ glamor_init_composite_shaders(ScreenPtr screen) key.solid_mask = TRUE; glamor_create_composite_shader(screen, &key); + memset(&key, 0, sizeof(key)); key.solid_source = TRUE; key.has_mask = FALSE; glamor_create_composite_shader(screen, &key); @@ -264,24 +246,6 @@ glamor_init_composite_shaders(ScreenPtr screen) glamor_create_composite_shader(screen, &key); } -static void -glamor_set_composite_transform_matrix(GLUmat4 *m, - PicturePtr picture, - float x_source, - float y_source) -{ - GLUmat4 temp; - DrawablePtr drawable = picture->pDrawable; - GLUvec4 scale = {{1.0f / drawable->width, - 1.0f / drawable->height, - 1.0, - 1.0}}; - - gluTranslate3f(m, -x_source, -y_source, 0.0); - gluScale4v(&temp, &scale); - gluMult4m_4m(m, &temp, m); -} - static Bool glamor_set_composite_op(ScreenPtr screen, CARD8 op, PicturePtr dest, PicturePtr mask) @@ -298,10 +262,6 @@ glamor_set_composite_op(ScreenPtr screen, source_blend = op_info->source_blend; dest_blend = op_info->dest_blend; - if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) != 0 && - op_info->source_alpha && source_blend != GL_ZERO) { - } - /* If there's no dst alpha channel, adjust the blend op so that we'll treat * it as always 1. */ @@ -336,12 +296,8 @@ glamor_set_composite_op(ScreenPtr screen, static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, - glamor_pixmap_private *pixmap_priv, - GLint transform_uniform_location, - int x_translate, int y_translate) + glamor_pixmap_private *pixmap_priv) { - GLUmat4 transform; - glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); switch (picture->repeatType) { @@ -376,13 +332,6 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, } glEnable(GL_TEXTURE_2D); - - glamor_set_composite_transform_matrix(&transform, - picture, - x_translate, - y_translate); - glUniformMatrix4fvARB(transform_uniform_location, 1, 0, - (float *)&transform); } static void @@ -447,15 +396,15 @@ glamor_get_picture_location(PicturePtr picture) } static Bool -glamor_composite_copy(CARD8 op, - PicturePtr source, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_dest, - INT16 y_dest, - CARD16 width, - CARD16 height) +glamor_composite_with_copy(CARD8 op, + PicturePtr source, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_dest, + INT16 y_dest, + CARD16 width, + CARD16 height) { RegionRec region; @@ -489,19 +438,59 @@ glamor_composite_copy(CARD8 op, return TRUE; } -void -glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, - INT16 y_dest, - CARD16 width, - CARD16 height) +static Bool +good_source_format(PicturePtr picture) +{ + switch (picture->format) { + case PICT_a8: + case PICT_a8r8g8b8: + return TRUE; + default: + glamor_fallback("Bad source format 0x%08x\n", picture->format); + return FALSE; + } +} + +static Bool +good_mask_format(PicturePtr picture) +{ + switch (picture->format) { + case PICT_a8: + case PICT_a8r8g8b8: + return TRUE; + default: + 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; + } +} + +static Bool +glamor_composite_with_shader(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, + INT16 y_dest, + CARD16 width, + CARD16 height) { ScreenPtr screen = dest->pDrawable->pScreen; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); @@ -510,38 +499,10 @@ glamor_composite(CARD8 op, glamor_pixmap_private *mask_pixmap_priv = NULL; struct shader_key key; glamor_composite_shader *shader; - GLUmat4 dest_to_dest; RegionRec region; + float vertices[4][2], source_texcoords[4][2], mask_texcoords[4][2]; int i; - - /* Do two-pass PictOpOver componentAlpha, until we enable - * dual source color blending. - */ - if (mask && mask->componentAlpha && 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; - } - - if (!mask) { - if (glamor_composite_copy(op, source, dest, - x_source, y_source, - x_dest, y_dest, - width, height)) - return; - } - - goto fail; + BoxPtr box; memset(&key, 0, sizeof(key)); key.has_mask = (mask != NULL); @@ -581,6 +542,8 @@ glamor_composite(CARD8 op, glamor_fallback("glamor_composite(): no FBO in source\n"); goto fail; } + if (!good_source_format(source)) + goto fail; } if (mask && !key.solid_mask) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); @@ -593,7 +556,11 @@ glamor_composite(CARD8 op, glamor_fallback("glamor_composite(): no FBO 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) { @@ -622,27 +589,16 @@ glamor_composite(CARD8 op, y_mask += mask->pDrawable->y; } - gluOrtho6f(&dest_to_dest, - dest_pixmap->screen_x, dest_pixmap->screen_x + width, - dest_pixmap->screen_y, dest_pixmap->screen_y + height, - -1, 1); - glUniformMatrix4fvARB(shader->dest_to_dest_uniform_location, 1, 0, - (float *)&dest_to_dest); - if (key.solid_source) { glamor_set_composite_solid(source, shader->source_uniform_location); } else { - glamor_set_composite_texture(screen, 0, source, source_pixmap_priv, - shader->dest_to_source_uniform_location, - x_source - x_dest, y_source - y_dest); + glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); } if (key.has_mask) { if (key.solid_mask) { glamor_set_composite_solid(mask, shader->mask_uniform_location); } else { - glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv, - shader->dest_to_mask_uniform_location, - x_mask - x_dest, y_mask - y_dest); + glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); } } @@ -652,25 +608,150 @@ glamor_composite(CARD8 op, x_mask, y_mask, x_dest, y_dest, width, height)) - return; + goto done; - glBegin(GL_QUADS); - for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { - BoxPtr box = ®ION_RECTS(®ion)[i]; - glVertex2i(box->x1, box->y1); - glVertex2i(box->x2, box->y1); - glVertex2i(box->x2, box->y2); - glVertex2i(box->x1, box->y2); + + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + + if (!key.solid_source) { + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); } - glEnd(); + if (key.has_mask && !key.solid_mask) { + glClientActiveTexture(GL_TEXTURE1); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, mask_texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + + box = REGION_RECTS(®ion); + for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { + vertices[0][0] = v_from_x_coord_x(dest_pixmap, box[i].x1); + vertices[0][1] = v_from_x_coord_y(dest_pixmap, box[i].y1); + vertices[1][0] = v_from_x_coord_x(dest_pixmap, box[i].x2); + vertices[1][1] = v_from_x_coord_y(dest_pixmap, box[i].y1); + vertices[2][0] = v_from_x_coord_x(dest_pixmap, box[i].x2); + vertices[2][1] = v_from_x_coord_y(dest_pixmap, box[i].y2); + vertices[3][0] = v_from_x_coord_x(dest_pixmap, box[i].x1); + vertices[3][1] = v_from_x_coord_y(dest_pixmap, box[i].y2); + + if (!key.solid_source) { + 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; + source_texcoords[0][0] = t_from_x_coord_x(source_pixmap, tx1); + source_texcoords[0][1] = t_from_x_coord_y(source_pixmap, ty1); + source_texcoords[1][0] = t_from_x_coord_x(source_pixmap, tx2); + source_texcoords[1][1] = t_from_x_coord_y(source_pixmap, ty1); + source_texcoords[2][0] = t_from_x_coord_x(source_pixmap, tx2); + source_texcoords[2][1] = t_from_x_coord_y(source_pixmap, ty2); + source_texcoords[3][0] = t_from_x_coord_x(source_pixmap, tx1); + source_texcoords[3][1] = t_from_x_coord_y(source_pixmap, ty2); + } + + if (key.has_mask && !key.solid_mask) { + int tx1 = box[i].x1 + x_mask - x_dest; + int ty1 = box[i].y1 + y_mask - y_dest; + int tx2 = box[i].x2 + x_mask - x_dest; + int ty2 = box[i].y2 + y_mask - y_dest; + mask_texcoords[0][0] = t_from_x_coord_x(mask_pixmap, tx1); + mask_texcoords[0][1] = t_from_x_coord_y(mask_pixmap, ty1); + mask_texcoords[1][0] = t_from_x_coord_x(mask_pixmap, tx2); + mask_texcoords[1][1] = t_from_x_coord_y(mask_pixmap, ty1); + mask_texcoords[2][0] = t_from_x_coord_x(mask_pixmap, tx2); + mask_texcoords[2][1] = t_from_x_coord_y(mask_pixmap, ty2); + mask_texcoords[3][0] = t_from_x_coord_x(mask_pixmap, tx1); + mask_texcoords[3][1] = t_from_x_coord_y(mask_pixmap, 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 + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } + + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glClientActiveTexture(GL_TEXTURE1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + +done: + 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); - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - - return; + return TRUE; fail: + glDisable(GL_BLEND); + glUseProgramObjectARB(0); + return FALSE; +} + +void +glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, + INT16 y_dest, + CARD16 width, + CARD16 height) +{ + /* Do two-pass PictOpOver componentAlpha, until we enable + * dual source color blending. + */ + if (mask && mask->componentAlpha) + goto fail; + if (mask && mask->componentAlpha && 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; + } + + if (!mask) { + if (glamor_composite_with_copy(op, source, dest, + x_source, y_source, + x_dest, y_dest, + width, height)) + return; + } + + if (glamor_composite_with_shader(op, source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height)) + return; + glamor_fallback("glamor_composite(): " "from picts %p/%p(%c,%c) to pict %p (%c)\n", source, mask, @@ -678,8 +759,9 @@ fail: glamor_get_picture_location(mask), dest, glamor_get_picture_location(dest)); - +fail: 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)) From f4a3194837e640997c0c3a775f48a49800e213c6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 23:17:09 -0600 Subject: [PATCH 075/462] glamor: Add the glyph cache from UXA (de-camelCased). This doesn't yet have an optimized glamor_composite_rects() implementation, but it does triple the speed of x11perf -aa10text. --- glamor/Makefile.am | 1 + glamor/glamor.c | 8 + glamor/glamor_glyphs.c | 877 +++++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 62 +++ glamor/glamor_render.c | 27 ++ 5 files changed, 975 insertions(+) create mode 100644 glamor/glamor_glyphs.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 17139c09f..e823234ae 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -23,6 +23,7 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ + glamor_glyphs.c \ glamor_polyfillrect.c \ glamor_polylines.c \ glamor_putimage.c \ diff --git a/glamor/glamor.c b/glamor/glamor.c index 7bc75aa13..03db7ecec 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -222,6 +222,8 @@ glamor_init(ScreenPtr screen) ps->Composite = glamor_composite; glamor_priv->saved_trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; + glamor_priv->saved_glyphs = ps->Glyphs; + ps->Glyphs = glamor_glyphs; #endif glamor_init_solid_shader(screen); @@ -230,6 +232,8 @@ glamor_init(ScreenPtr screen) glamor_init_composite_shaders(screen); glamor_init_finish_access_shaders(screen); + glamor_glyphs_init(screen); + return TRUE; fail: @@ -246,6 +250,8 @@ glamor_fini(ScreenPtr screen) PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif + glamor_glyphs_fini(screen); + screen->CreateGC = glamor_priv->saved_create_gc; screen->CreatePixmap = glamor_priv->saved_create_pixmap; screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; @@ -255,5 +261,7 @@ glamor_fini(ScreenPtr screen) screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; #ifdef RENDER ps->Composite = glamor_priv->saved_composite; + ps->Trapezoids = glamor_priv->saved_trapezoids; + ps->Glyphs = glamor_priv->saved_glyphs; #endif } diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c new file mode 100644 index 000000000..7b2d13d0f --- /dev/null +++ b/glamor/glamor_glyphs.c @@ -0,0 +1,877 @@ +/* + * Copyright © 2008 Red Hat, Inc. + * Partly based on code Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor + * Based on code by: Keith Packard + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "glamor_priv.h" + +#include "mipict.h" + +#if DEBUG_GLYPH_CACHE +#define DBG_GLYPH_CACHE(a) ErrorF a +#else +#define DBG_GLYPH_CACHE(a) +#endif + +/* Width of the pixmaps we use for the caches; this should be less than + * max texture size of the driver; this may need to actually come from + * the driver. + */ +#define CACHE_PICTURE_WIDTH 1024 + +/* Maximum number of glyphs we buffer on the stack before flushing + * rendering to the mask or destination surface. + */ +#define GLYPH_BUFFER_SIZE 256 + +typedef struct { + PicturePtr source; + glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE]; + int count; +} glamor_glyph_buffer_t; + +typedef enum { + GLAMOR_GLYPH_SUCCESS, /* Glyph added to render buffer */ + GLAMOR_GLYPH_FAIL, /* out of memory, etc */ + GLAMOR_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ +} glamor_glyph_cache_result_t; + +void glamor_glyphs_init(ScreenPtr screen) +{ + glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); + int i = 0; + + memset(glamor_screen->glyph_caches, 0, sizeof(glamor_screen->glyph_caches)); + + glamor_screen->glyph_caches[i].format = PICT_a8; + glamor_screen->glyph_caches[i].glyph_width = + glamor_screen->glyph_caches[i].glyph_height = 16; + i++; + glamor_screen->glyph_caches[i].format = PICT_a8; + glamor_screen->glyph_caches[i].glyph_width = + glamor_screen->glyph_caches[i].glyph_height = 32; + i++; + glamor_screen->glyph_caches[i].format = PICT_a8r8g8b8; + glamor_screen->glyph_caches[i].glyph_width = + glamor_screen->glyph_caches[i].glyph_height = 16; + i++; + glamor_screen->glyph_caches[i].format = PICT_a8r8g8b8; + glamor_screen->glyph_caches[i].glyph_width = + glamor_screen->glyph_caches[i].glyph_height = 32; + i++; + + assert(i == GLAMOR_NUM_GLYPH_CACHES); + + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { + glamor_screen->glyph_caches[i].columns = + CACHE_PICTURE_WIDTH / glamor_screen->glyph_caches[i].glyph_width; + glamor_screen->glyph_caches[i].size = 256; + glamor_screen->glyph_caches[i].hash_size = 557; + } +} + +static void glamor_unrealize_glyph_caches(ScreenPtr screen, unsigned int format) +{ + glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); + int i; + + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { + glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; + + if (cache->format != format) + continue; + + if (cache->picture) { + FreePicture((pointer) cache->picture, (XID) 0); + cache->picture = NULL; + } + + if (cache->hash_entries) { + xfree(cache->hash_entries); + cache->hash_entries = NULL; + } + + if (cache->glyphs) { + xfree(cache->glyphs); + cache->glyphs = NULL; + } + cache->glyph_count = 0; + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +/* All caches for a single format share a single pixmap for glyph storage, + * allowing mixing glyphs of different sizes without paying a penalty + * for switching between source pixmaps. (Note that for a size of font + * right at the border between two sizes, we might be switching for almost + * every glyph.) + * + * This function allocates the storage pixmap, and then fills in the + * rest of the allocated structures for all caches with the given format. + */ +static Bool glamor_realize_glyph_caches(ScreenPtr screen, unsigned int format) +{ + glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); + int depth = PIXMAN_FORMAT_DEPTH(format); + PictFormatPtr pict_format; + PixmapPtr pixmap; + PicturePtr picture; + CARD32 component_alpha; + int height; + int i; + int error; + + pict_format = PictureMatchFormat(screen, depth, format); + if (!pict_format) + return FALSE; + + /* Compute the total vertical size needed for the format */ + + height = 0; + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { + glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; + int rows; + + if (cache->format != format) + continue; + + cache->y_offset = height; + + rows = (cache->size + cache->columns - 1) / cache->columns; + height += rows * cache->glyph_height; + } + + /* Now allocate the pixmap and picture */ + + pixmap = screen->CreatePixmap(screen, + CACHE_PICTURE_WIDTH, + height, depth, + 0); + if (!pixmap) + return FALSE; + + component_alpha = NeedsComponent(pict_format->format); + picture = CreatePicture(0, &pixmap->drawable, pict_format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + + screen->DestroyPixmap(pixmap); /* picture holds a refcount */ + + if (!picture) + return FALSE; + + /* And store the picture in all the caches for the format */ + + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { + glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; + int j; + + if (cache->format != format) + continue; + + cache->picture = picture; + cache->picture->refcnt++; + cache->hash_entries = xalloc(sizeof(int) * cache->hash_size); + cache->glyphs = + xalloc(sizeof(glamor_cached_glyph_t) * cache->size); + cache->glyph_count = 0; + + if (!cache->hash_entries || !cache->glyphs) + goto bail; + + for (j = 0; j < cache->hash_size; j++) + cache->hash_entries[j] = -1; + + cache->eviction_position = rand() % cache->size; + } + + /* Each cache references the picture individually */ + FreePicture(picture, 0); + return TRUE; + + bail: + glamor_unrealize_glyph_caches(screen, format); + return FALSE; +} + +void glamor_glyphs_fini(ScreenPtr screen) +{ + glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); + int i; + + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { + glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; + + if (cache->picture) + glamor_unrealize_glyph_caches(screen, cache->format); + } +} + +static int +glamor_glyph_cache_hash_lookup(glamor_glyph_cache_t * cache, GlyphPtr glyph) +{ + int slot; + + slot = (*(CARD32 *) glyph->sha1) % cache->hash_size; + + while (TRUE) { /* hash table can never be full */ + int entryPos = cache->hash_entries[slot]; + if (entryPos == -1) + return -1; + + if (memcmp(glyph->sha1, cache->glyphs[entryPos].sha1, + sizeof(glyph->sha1)) == 0) { + return entryPos; + } + + slot--; + if (slot < 0) + slot = cache->hash_size - 1; + } +} + +static void +glamor_glyph_cache_hash_insert(glamor_glyph_cache_t * cache, GlyphPtr glyph, int pos) +{ + int slot; + + memcpy(cache->glyphs[pos].sha1, glyph->sha1, sizeof(glyph->sha1)); + + slot = (*(CARD32 *) glyph->sha1) % cache->hash_size; + + while (TRUE) { /* hash table can never be full */ + if (cache->hash_entries[slot] == -1) { + cache->hash_entries[slot] = pos; + return; + } + + slot--; + if (slot < 0) + slot = cache->hash_size - 1; + } +} + +static void glamor_glyph_cache_hash_remove(glamor_glyph_cache_t * cache, int pos) +{ + int slot; + int emptied_slot = -1; + + slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hash_size; + + while (TRUE) { /* hash table can never be full */ + int entryPos = cache->hash_entries[slot]; + + if (entryPos == -1) + return; + + if (entryPos == pos) { + cache->hash_entries[slot] = -1; + emptied_slot = slot; + } else if (emptied_slot != -1) { + /* See if we can move this entry into the emptied slot, + * we can't do that if if entry would have hashed + * between the current position and the emptied slot. + * (taking wrapping into account). Bad positions + * are: + * + * | XXXXXXXXXX | + * i j + * + * |XXX XXXX| + * j i + * + * i - slot, j - emptied_slot + * + * (Knuth 6.4R) + */ + + int entry_slot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % + cache->hash_size; + + if (!((entry_slot >= slot && entry_slot < emptied_slot) || + (emptied_slot < slot + && (entry_slot < emptied_slot + || entry_slot >= slot)))) { + cache->hash_entries[emptied_slot] = entryPos; + cache->hash_entries[slot] = -1; + emptied_slot = slot; + } + } + + slot--; + if (slot < 0) + slot = cache->hash_size - 1; + } +} + +#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyph_width) +#define CACHE_Y(pos) (cache->y_offset + ((pos) / cache->columns) * cache->glyph_height) + +/* The most efficient thing to way to upload the glyph to the screen + * is to use CopyArea; glamor pixmaps are always offscreen. + */ +static Bool +glamor_glyph_cache_upload_glyph(ScreenPtr screen, + glamor_glyph_cache_t * cache, + int pos, GlyphPtr glyph) +{ + PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; + PixmapPtr glyph_pixmap = (PixmapPtr) glyph_picture->pDrawable; + PixmapPtr cache_pixmap = (PixmapPtr) cache->picture->pDrawable; + PixmapPtr scratch; + GCPtr gc; + + /* UploadToScreen only works if bpp match */ + if (glyph_pixmap->drawable.bitsPerPixel != + cache_pixmap->drawable.bitsPerPixel) + return FALSE; + + gc = GetScratchGC(cache_pixmap->drawable.depth, screen); + ValidateGC(&cache_pixmap->drawable, gc); + + /* Create a temporary bo to stream the updates to the cache */ + scratch = screen->CreatePixmap(screen, + glyph->info.width, + glyph->info.height, + glyph_pixmap->drawable.depth, + 0); + if (scratch) { + (void)glamor_copy_area(&glyph_pixmap->drawable, + &scratch->drawable, + gc, + 0, 0, + glyph->info.width, glyph->info.height, + 0, 0); + } else { + scratch = glyph_pixmap; + } + + (void)glamor_copy_area(&scratch->drawable, + &cache_pixmap->drawable, + gc, + 0, 0, glyph->info.width, glyph->info.height, + CACHE_X(pos), CACHE_Y(pos)); + + if (scratch != glyph_pixmap) + screen->DestroyPixmap(scratch); + + FreeScratchGC(gc); + + return TRUE; +} + +static glamor_glyph_cache_result_t +glamor_glyph_cache_buffer_glyph(ScreenPtr screen, + glamor_glyph_cache_t * cache, + glamor_glyph_buffer_t * buffer, + GlyphPtr glyph, int x_glyph, int y_glyph) +{ + glamor_composite_rect_t *rect; + int pos; + + if (buffer->source && buffer->source != cache->picture) + return GLAMOR_GLYPH_NEED_FLUSH; + + if (!cache->picture) { + if (!glamor_realize_glyph_caches(screen, cache->format)) + return GLAMOR_GLYPH_FAIL; + } + + DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n", + cache->glyph_width, cache->glyph_height, + cache->format == PICT_a8 ? "A" : "ARGB", + (long)*(CARD32 *) glyph->sha1)); + + pos = glamor_glyph_cache_hash_lookup(cache, glyph); + if (pos != -1) { + DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos)); + } else { + if (cache->glyph_count < cache->size) { + /* Space remaining; we fill from the start */ + pos = cache->glyph_count; + cache->glyph_count++; + DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos)); + + glamor_glyph_cache_hash_insert(cache, glyph, pos); + + } else { + /* Need to evict an entry. We have to see if any glyphs + * already in the output buffer were at this position in + * the cache + */ + + pos = cache->eviction_position; + DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); + if (buffer->count) { + int x, y; + int i; + + x = CACHE_X(pos); + y = CACHE_Y(pos); + + for (i = 0; i < buffer->count; i++) { + if (buffer->rects[i].x_src == x + && buffer->rects[i].y_src == y) { + DBG_GLYPH_CACHE((" must flush buffer\n")); + return GLAMOR_GLYPH_NEED_FLUSH; + } + } + } + + /* OK, we're all set, swap in the new glyph */ + glamor_glyph_cache_hash_remove(cache, pos); + glamor_glyph_cache_hash_insert(cache, glyph, pos); + + /* And pick a new eviction position */ + cache->eviction_position = rand() % cache->size; + } + + /* Now actually upload the glyph into the cache picture; if + * we can't do it with UploadToScreen (because the glyph is + * offscreen, etc), we fall back to CompositePicture. + */ + if (!glamor_glyph_cache_upload_glyph(screen, cache, pos, glyph)) { + CompositePicture(PictOpSrc, + GlyphPicture(glyph)[screen->myNum], + None, + cache->picture, + 0, 0, + 0, 0, + CACHE_X(pos), + CACHE_Y(pos), + glyph->info.width, + glyph->info.height); + } + + } + + buffer->source = cache->picture; + + rect = &buffer->rects[buffer->count]; + rect->x_src = CACHE_X(pos); + rect->y_src = CACHE_Y(pos); + rect->x_dst = x_glyph - glyph->info.x; + rect->y_dst = y_glyph - glyph->info.y; + rect->width = glyph->info.width; + rect->height = glyph->info.height; + + buffer->count++; + + return GLAMOR_GLYPH_SUCCESS; +} + +#undef CACHE_X +#undef CACHE_Y + +static glamor_glyph_cache_result_t +glamor_buffer_glyph(ScreenPtr screen, + glamor_glyph_buffer_t *buffer, + GlyphPtr glyph, int x_glyph, int y_glyph) +{ + glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); + unsigned int format = (GlyphPicture(glyph)[screen->myNum])->format; + int width = glyph->info.width; + int height = glyph->info.height; + glamor_composite_rect_t *rect; + PicturePtr source; + int i; + + if (buffer->count == GLYPH_BUFFER_SIZE) + return GLAMOR_GLYPH_NEED_FLUSH; + + if (PICT_FORMAT_BPP(format) == 1) + format = PICT_a8; + + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { + glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; + + if (format == cache->format && + width <= cache->glyph_width && + height <= cache->glyph_height) { + glamor_glyph_cache_result_t result = + glamor_glyph_cache_buffer_glyph(screen, + &glamor_screen->glyph_caches[i], + buffer, + glyph, x_glyph, + y_glyph); + switch (result) { + case GLAMOR_GLYPH_FAIL: + break; + case GLAMOR_GLYPH_SUCCESS: + case GLAMOR_GLYPH_NEED_FLUSH: + return result; + } + } + } + + /* Couldn't find the glyph in the cache, use the glyph picture directly */ + + source = GlyphPicture(glyph)[screen->myNum]; + if (buffer->source && buffer->source != source) + return GLAMOR_GLYPH_NEED_FLUSH; + + buffer->source = source; + + rect = &buffer->rects[buffer->count]; + rect->x_src = 0; + rect->y_src = 0; + rect->x_dst = x_glyph - glyph->info.x; + rect->y_dst = y_glyph - glyph->info.y; + rect->width = glyph->info.width; + rect->height = glyph->info.height; + + buffer->count++; + + return GLAMOR_GLYPH_SUCCESS; +} + +static void glamor_glyphs_to_mask(PicturePtr mask, + glamor_glyph_buffer_t *buffer) +{ + glamor_composite_rects(PictOpAdd, buffer->source, mask, + buffer->count, buffer->rects); + + buffer->count = 0; + buffer->source = NULL; +} + +static void +glamor_glyphs_to_dst(CARD8 op, + PicturePtr src, + PicturePtr dst, + glamor_glyph_buffer_t *buffer, + INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst) +{ + int i; + + for (i = 0; i < buffer->count; i++) { + glamor_composite_rect_t *rect = &buffer->rects[i]; + + CompositePicture(op, + src, + buffer->source, + dst, + x_src + rect->x_dst - x_dst, + y_src + rect->y_dst - y_dst, + rect->x_src, + rect->y_src, + rect->x_dst, + rect->y_dst, rect->width, rect->height); + } + + buffer->count = 0; + buffer->source = NULL; +} + +/* Cut and paste from render/glyph.c - probably should export it instead */ +static void +glamor_glyph_extents(int nlist, + GlyphListPtr list, GlyphPtr *glyphs, BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +/** + * Returns TRUE if the glyphs in the lists intersect. Only checks based on + * bounding box, which appears to be good enough to catch most cases at least. + */ +static Bool +glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + BoxRec extents; + Bool first = TRUE; + + x = 0; + y = 0; + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = 0; + extents.y2 = 0; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + glyph = *glyphs++; + + if (glyph->info.width == 0 || glyph->info.height == 0) { + x += glyph->info.xOff; + y += glyph->info.yOff; + continue; + } + + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + + if (first) { + extents.x1 = x1; + extents.y1 = y1; + extents.x2 = x2; + extents.y2 = y2; + first = FALSE; + } else { + if (x1 < extents.x2 && x2 > extents.x1 && + y1 < extents.y2 && y2 > extents.y1) { + return TRUE; + } + + if (x1 < extents.x1) + extents.x1 = x1; + if (x2 > extents.x2) + extents.x2 = x2; + if (y1 < extents.y1) + extents.y1 = y1; + if (y2 > extents.y2) + extents.y2 = y2; + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } + + return FALSE; +} + +void +glamor_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + PicturePtr picture; + PixmapPtr mask_pixmap = 0; + PicturePtr mask; + ScreenPtr screen = dst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int x_dst = list->xOff, y_dst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents = { 0, 0, 0, 0 }; + CARD32 component_alpha; + glamor_glyph_buffer_t buffer; + + /* If we don't have a mask format but all the glyphs have the same format + * and don't intersect, use the glyph format as mask format for the full + * benefits of the glyph cache. + */ + if (!mask_format) { + Bool same_format = TRUE; + int i; + + mask_format = list[0].format; + + for (i = 0; i < nlist; i++) { + if (mask_format->format != list[i].format->format) { + same_format = FALSE; + break; + } + } + + if (!same_format || (mask_format->depth != 1 && + glamor_glyphs_intersect(nlist, list, + glyphs))) { + mask_format = NULL; + } + } + + if (mask_format) { + GCPtr gc; + xRectangle rect; + + glamor_glyph_extents(nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + + if (mask_format->depth == 1) { + PictFormatPtr a8Format = + PictureMatchFormat(screen, 8, PICT_a8); + + if (a8Format) + mask_format = a8Format; + } + + mask_pixmap = screen->CreatePixmap(screen, width, height, + mask_format->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!mask_pixmap) + return; + component_alpha = NeedsComponent(mask_format->format); + mask = CreatePicture(0, &mask_pixmap->drawable, + mask_format, CPComponentAlpha, + &component_alpha, serverClient, &error); + if (!mask) { + screen->DestroyPixmap(mask_pixmap); + return; + } + gc = GetScratchGC(mask_pixmap->drawable.depth, screen); + ValidateGC(&mask_pixmap->drawable, gc); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + gc->ops->PolyFillRect(&mask_pixmap->drawable, gc, 1, &rect); + FreeScratchGC(gc); + x = -extents.x1; + y = -extents.y1; + } else { + mask = dst; + x = 0; + y = 0; + } + buffer.count = 0; + buffer.source = NULL; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + glyph = *glyphs++; + picture = GlyphPicture(glyph)[screen->myNum]; + + if (glyph->info.width > 0 && glyph->info.height > 0 && + glamor_buffer_glyph(screen, &buffer, glyph, x, + y) == GLAMOR_GLYPH_NEED_FLUSH) { + if (mask_format) + glamor_glyphs_to_mask(mask, &buffer); + else + glamor_glyphs_to_dst(op, src, dst, + &buffer, x_src, y_src, + x_dst, y_dst); + + glamor_buffer_glyph(screen, &buffer, glyph, x, y); + } + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + + if (buffer.count) { + if (mask_format) + glamor_glyphs_to_mask(mask, &buffer); + else + glamor_glyphs_to_dst(op, src, dst, &buffer, + x_src, y_src, x_dst, y_dst); + } + + if (mask_format) { + x = extents.x1; + y = extents.y1; + CompositePicture(op, + src, + mask, + dst, + x_src + x - x_dst, + y_src + y - y_dst, 0, 0, x, y, width, height); + FreePicture(mask, 0); + screen->DestroyPixmap(mask_pixmap); + } +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 526b2cf3a..dc1a5ca87 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -31,6 +31,10 @@ #include "glamor.h" #include +#ifdef RENDER +#include "glyphstr.h" +#endif + typedef enum glamor_access { GLAMOR_ACCESS_RO, GLAMOR_ACCESS_RW, @@ -52,6 +56,48 @@ typedef struct glamor_composite_shader { GLint mask_uniform_location; } glamor_composite_shader; +typedef struct { + INT16 x_src; + INT16 y_src; + INT16 x_dst; + INT16 y_dst; + INT16 width; + INT16 height; +} glamor_composite_rect_t; + +typedef struct { + 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; + + /* 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; + + 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 */ +} glamor_glyph_cache_t; + +#define GLAMOR_NUM_GLYPH_CACHES 4 + typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; @@ -60,6 +106,7 @@ typedef struct glamor_screen_private { 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; @@ -84,6 +131,8 @@ typedef struct glamor_screen_private { /* glamor_composite */ glamor_composite_shader composite_shader[8]; + + glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; } glamor_screen_private; typedef struct glamor_pixmap_private { @@ -241,6 +290,16 @@ glamor_get_spans(DrawablePtr drawable, int nspans, char *dst_start); +/* glamor_glyphs.c */ +void glamor_glyphs_init(ScreenPtr screen); +void glamor_glyphs_fini(ScreenPtr screen); +void glamor_glyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); + /* glamor_setspans.c */ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted); @@ -281,6 +340,9 @@ void glamor_trapezoids(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid *traps); void glamor_init_composite_shaders(ScreenPtr screen); +void glamor_composite_rects(CARD8 op, + PicturePtr src, PicturePtr dst, + int nrect, glamor_composite_rect_t *rects); /* glamor_tile.c */ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index be28bd4e0..e4a9441a4 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -921,4 +921,31 @@ glamor_trapezoids(CARD8 op, FreePicture(picture, 0); } +void +glamor_composite_rects(CARD8 op, + PicturePtr src, PicturePtr dst, + int nrect, glamor_composite_rect_t *rects) +{ + int n; + glamor_composite_rect_t *r; + + ValidatePicture(src); + ValidatePicture(dst); + + 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++; + } +} + #endif /* RENDER */ From 126fc09cb5bf8c38b73f1c2cd2a0ef588c3265e8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 22:35:04 -0800 Subject: [PATCH 076/462] glamor: Rework the Render shader setup to be easily modified, like cairo-gl. --- glamor/glamor_priv.h | 16 +++- glamor/glamor_render.c | 181 +++++++++++++++++++++-------------------- 2 files changed, 108 insertions(+), 89 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index dc1a5ca87..95aad7da1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -98,6 +98,19 @@ typedef struct { #define GLAMOR_NUM_GLYPH_CACHES 4 +enum shader_source { + SHADER_SOURCE_SOLID, + SHADER_SOURCE_TEXTURE_ALPHA, + SHADER_SOURCE_COUNT, +}; + +enum shader_mask { + SHADER_MASK_NONE, + SHADER_MASK_SOLID, + SHADER_MASK_TEXTURE_ALPHA, + SHADER_MASK_COUNT, +}; + typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; @@ -130,7 +143,8 @@ typedef struct glamor_screen_private { GLint put_image_xybitmap_bg_uniform_location; /* glamor_composite */ - glamor_composite_shader composite_shader[8]; + glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] + [SHADER_MASK_COUNT]; glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; } glamor_screen_private; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e4a9441a4..f432b5f29 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -39,9 +39,8 @@ #include "glu3/glu3.h" struct shader_key { - Bool solid_source; - Bool has_mask; - Bool solid_mask; + enum shader_source source; + enum shader_mask mask; }; struct blendinfo { @@ -67,29 +66,6 @@ static struct blendinfo composite_op_info[] = { [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, }; -#define SOLID_SOURCE_INDEX 1 -#define HAS_MASK_INDEX 2 -#define SOLID_MASK_INDEX 3 - -static glamor_composite_shader * -glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) -{ - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - int index = 0; - - if (key->solid_source) - index += SOLID_SOURCE_INDEX; - if (key->has_mask) { - index += HAS_MASK_INDEX; - if (key->solid_mask) - index += SOLID_MASK_INDEX; - } - - assert(index < ARRAY_SIZE(glamor_priv->composite_shader)); - - return &glamor_priv->composite_shader[index]; -} - static GLuint glamor_create_composite_fs(struct shader_key *key) { @@ -104,12 +80,12 @@ glamor_create_composite_fs(struct shader_key *key) const char *main_opening = "void main()\n" "{\n"; - const char *source_pixmap_fetch = + const char *source_alpha_pixmap_fetch = " vec4 source = texture2D(source_sampler, gl_TexCoord[0].xy);\n"; - const char *mask_pixmap_fetch = + const char *mask_alpha_pixmap_fetch = " vec4 mask = texture2D(mask_sampler, gl_TexCoord[1].xy);\n"; const char *source_in_mask = - " gl_FragColor = source * mask.w;\n"; + " gl_FragColor = source * mask.a;\n"; const char *source_only = " gl_FragColor = source;\n"; const char *main_closing = @@ -119,29 +95,49 @@ glamor_create_composite_fs(struct shader_key *key) const char *source_fetch = ""; const char *mask_setup = ""; const char *mask_fetch = ""; + const char *in; GLuint prog; - if (key->solid_source) { + switch (key->source) { + case SHADER_SOURCE_SOLID: source_setup = source_solid_header; - } else { + break; + case SHADER_SOURCE_TEXTURE_ALPHA: source_setup = source_pixmap_header; - source_fetch = source_pixmap_fetch; + source_fetch = source_alpha_pixmap_fetch; + break; + FatalError("Bad composite shader source"); + default: + FatalError("Bad composite source mask"); } - if (key->has_mask) { - if (key->solid_mask) { - mask_setup = mask_solid_header; - } else { - mask_setup = mask_pixmap_header; - mask_fetch = mask_pixmap_fetch; - } + + switch (key->mask) { + case SHADER_MASK_NONE: + break; + case SHADER_MASK_SOLID: + mask_setup = mask_solid_header; + break; + case SHADER_MASK_TEXTURE_ALPHA: + mask_setup = mask_pixmap_header; + mask_fetch = mask_alpha_pixmap_fetch; + break; + default: + FatalError("Bad composite shader mask"); } + + if (key->mask == SHADER_MASK_NONE) { + in = source_only; + } else { + in = source_in_mask; + } + source = XNFprintf("%s%s%s%s%s%s%s", source_setup, mask_setup, main_opening, source_fetch, mask_fetch, - key->has_mask ? source_in_mask : source_only, + in, main_closing); prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); @@ -156,19 +152,28 @@ glamor_create_composite_vs(struct shader_key *key) const char *main_opening = "void main()\n" "{\n" - " gl_Position = gl_Vertex;\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; - Bool compute_mask_coords = key->has_mask && !key->solid_mask; - source = XNFprintf("%s%s%s", + 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; + + source = XNFprintf("%s%s%s%s", main_opening, - compute_mask_coords ? mask_coords : "", + source_coords_setup, + mask_coords_setup, main_closing); prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); @@ -178,13 +183,11 @@ glamor_create_composite_vs(struct shader_key *key) } static void -glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) +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; - glamor_composite_shader *shader; - - shader = glamor_lookup_composite_shader(screen, key); vs = glamor_create_composite_vs(key); if (vs == 0) @@ -202,7 +205,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) glUseProgramObjectARB(prog); - if (key->solid_source) { + if (key->source == SHADER_SOURCE_SOLID) { shader->source_uniform_location = glGetUniformLocationARB(prog, "source"); } else { @@ -211,8 +214,8 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) glUniform1i(source_sampler_uniform_location, 0); } - if (key->has_mask) { - if (key->solid_mask) { + if (key->mask != SHADER_MASK_NONE) { + if (key->mask == SHADER_MASK_SOLID) { shader->mask_uniform_location = glGetUniformLocationARB(prog, "mask"); } else { @@ -223,27 +226,22 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) } } +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; + + shader = &glamor_priv->composite_shader[key->source][key->mask]; + if (shader->prog == 0) + glamor_create_composite_shader(screen, key, shader); + + return shader; +} + void glamor_init_composite_shaders(ScreenPtr screen) { - struct shader_key key; - - memset(&key, 0, sizeof(key)); - key.has_mask = FALSE; - glamor_create_composite_shader(screen, &key); - key.has_mask = TRUE; - glamor_create_composite_shader(screen, &key); - key.solid_mask = TRUE; - glamor_create_composite_shader(screen, &key); - - memset(&key, 0, sizeof(key)); - key.solid_source = TRUE; - key.has_mask = FALSE; - glamor_create_composite_shader(screen, &key); - key.has_mask = TRUE; - glamor_create_composite_shader(screen, &key); - key.solid_mask = TRUE; - glamor_create_composite_shader(screen, &key); } static Bool @@ -505,33 +503,40 @@ glamor_composite_with_shader(CARD8 op, BoxPtr box; memset(&key, 0, sizeof(key)); - key.has_mask = (mask != NULL); if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeSolidFill) { - key.solid_source = TRUE; + key.source = SHADER_SOURCE_SOLID; } else { - ErrorF("gradient source\n"); + glamor_fallback("gradient source\n"); goto fail; } + } else { + key.source = SHADER_SOURCE_TEXTURE_ALPHA; } - if (mask && !mask->pDrawable) { - if (mask->pSourcePict->type == SourcePictTypeSolidFill) { - key.solid_mask = TRUE; + if (mask) { + if (!mask->pDrawable) { + if (mask->pSourcePict->type == SourcePictTypeSolidFill) { + key.mask = SHADER_MASK_SOLID; + } else { + glamor_fallback("gradient mask\n"); + goto fail; + } } else { - ErrorF("gradient mask\n"); - goto fail; + key.mask = SHADER_MASK_TEXTURE_ALPHA; } + } else { + key.mask = SHADER_MASK_NONE; } if (source->alphaMap) { - ErrorF("source alphaMap\n"); + glamor_fallback("source alphaMap\n"); goto fail; } if (mask && mask->alphaMap) { - ErrorF("mask alphaMap\n"); + glamor_fallback("mask alphaMap\n"); goto fail; } - if (!key.solid_source) { + if (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) { @@ -545,7 +550,7 @@ glamor_composite_with_shader(CARD8 op, if (!good_source_format(source)) goto fail; } - if (mask && !key.solid_mask) { + if (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) { @@ -589,13 +594,13 @@ glamor_composite_with_shader(CARD8 op, y_mask += mask->pDrawable->y; } - if (key.solid_source) { + 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.has_mask) { - if (key.solid_mask) { + 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); @@ -614,13 +619,13 @@ glamor_composite_with_shader(CARD8 op, glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - if (!key.solid_source) { + if (key.source != SHADER_SOURCE_SOLID) { glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } - if (key.has_mask && !key.solid_mask) { + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { glClientActiveTexture(GL_TEXTURE1); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, mask_texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -637,7 +642,7 @@ glamor_composite_with_shader(CARD8 op, vertices[3][0] = v_from_x_coord_x(dest_pixmap, box[i].x1); vertices[3][1] = v_from_x_coord_y(dest_pixmap, box[i].y2); - if (!key.solid_source) { + 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; @@ -652,7 +657,7 @@ glamor_composite_with_shader(CARD8 op, source_texcoords[3][1] = t_from_x_coord_y(source_pixmap, ty2); } - if (key.has_mask && !key.solid_mask) { + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { int tx1 = box[i].x1 + x_mask - x_dest; int ty1 = box[i].y1 + y_mask - y_dest; int tx2 = box[i].x2 + x_mask - x_dest; From be64167fea3c74447ed3c5116b97473676c25b29 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 09:20:50 -0800 Subject: [PATCH 077/462] glamor: Don't try to CopyArea from a Solid source picture. Fixes failure with rendercheck. --- glamor/glamor_render.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f432b5f29..0f4f4c0af 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -406,6 +406,9 @@ glamor_composite_with_copy(CARD8 op, { RegionRec region; + if (!source->pDrawable) + return FALSE; + if (!compatible_formats(op, dest, source)) return FALSE; From e6bf50573650f03c8130b7783485b24e98e15c79 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 09:23:09 -0800 Subject: [PATCH 078/462] glamor: Set active texture on glamor_copy_n_to_n setup. Fixes failure in rendercheck -t blend -o src --- glamor/glamor_copyarea.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 695edc3e9..f21752b42 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -74,6 +74,7 @@ glamor_copy_n_to_n(DrawablePtr src, goto fail; } + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); From 0565c1d789ed82c533f860713d66b4941c299f9c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 9 Feb 2010 22:35:04 -0800 Subject: [PATCH 079/462] glamor: Add support for accel of x8r8g8b8 source pictures. There's a limitation still for RepeatNone, but this fixes a bunch of fallbacks for gnome-terminal. --- glamor/glamor_priv.h | 2 ++ glamor/glamor_render.c | 51 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 95aad7da1..283f7ea12 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -100,6 +100,7 @@ typedef struct { enum shader_source { SHADER_SOURCE_SOLID, + SHADER_SOURCE_TEXTURE, SHADER_SOURCE_TEXTURE_ALPHA, SHADER_SOURCE_COUNT, }; @@ -107,6 +108,7 @@ enum shader_source { enum shader_mask { SHADER_MASK_NONE, SHADER_MASK_SOLID, + SHADER_MASK_TEXTURE, SHADER_MASK_TEXTURE_ALPHA, SHADER_MASK_COUNT, }; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 0f4f4c0af..cb9da1e1a 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -82,8 +82,14 @@ glamor_create_composite_fs(struct shader_key *key) "{\n"; const char *source_alpha_pixmap_fetch = " vec4 source = texture2D(source_sampler, gl_TexCoord[0].xy);\n"; + const char *source_pixmap_fetch = + " vec4 source = vec4(texture2D(source_sampler, " + " gl_TexCoord[0].xy).rgb, 1.0);\n"; const char *mask_alpha_pixmap_fetch = " vec4 mask = texture2D(mask_sampler, gl_TexCoord[1].xy);\n"; + const char *mask_pixmap_fetch = + " vec4 mask = vec4(texture2D(mask_sampler, " + " gl_TexCoord[1].xy).rgb, 1.0);\n"; const char *source_in_mask = " gl_FragColor = source * mask.a;\n"; const char *source_only = @@ -106,9 +112,12 @@ glamor_create_composite_fs(struct shader_key *key) source_setup = source_pixmap_header; source_fetch = source_alpha_pixmap_fetch; break; - FatalError("Bad composite shader source"); + case SHADER_SOURCE_TEXTURE: + source_setup = source_pixmap_header; + source_fetch = source_pixmap_fetch; + break; default: - FatalError("Bad composite source mask"); + FatalError("Bad composite shader source"); } switch (key->mask) { @@ -121,6 +130,10 @@ glamor_create_composite_fs(struct shader_key *key) mask_setup = mask_pixmap_header; mask_fetch = mask_alpha_pixmap_fetch; break; + case SHADER_MASK_TEXTURE: + mask_setup = mask_pixmap_header; + mask_fetch = mask_pixmap_fetch; + break; default: FatalError("Bad composite shader mask"); } @@ -446,6 +459,14 @@ good_source_format(PicturePtr picture) case PICT_a8: case PICT_a8r8g8b8: return TRUE; + case PICT_x8r8g8b8: + /* In order to support formats with no alpha, we have to wire the + * alpha to 1 in the shader, which conflicts with + * GL_CLAMP_TO_BORDERing to transparent. We could possibly compute + * coverage of the texels in the sampling area if we need to, but + * that isn't implemented today. + */ + return (picture->repeatType != RepeatNone); default: glamor_fallback("Bad source format 0x%08x\n", picture->format); return FALSE; @@ -459,6 +480,14 @@ good_mask_format(PicturePtr picture) case PICT_a8: case PICT_a8r8g8b8: return TRUE; + case PICT_x8r8g8b8: + /* In order to support formats with no alpha, we have to wire the + * alpha to 1 in the shader, which conflicts with + * GL_CLAMP_TO_BORDERing to transparent. We could possibly compute + * coverage of the texels in the sampling area if we need to, but + * that isn't implemented today. + */ + return (picture->repeatType != RepeatNone); default: glamor_fallback("Bad mask format 0x%08x\n", picture->format); return FALSE; @@ -514,7 +543,11 @@ glamor_composite_with_shader(CARD8 op, goto fail; } } else { - key.source = SHADER_SOURCE_TEXTURE_ALPHA; + if (PICT_FORMAT_A(source->format) != 0) { + key.source = SHADER_SOURCE_TEXTURE_ALPHA; + } else { + key.source = SHADER_SOURCE_TEXTURE; + } } if (mask) { if (!mask->pDrawable) { @@ -525,7 +558,11 @@ glamor_composite_with_shader(CARD8 op, goto fail; } } else { - key.mask = SHADER_MASK_TEXTURE_ALPHA; + if (PICT_FORMAT_A(mask->format) != 0) { + key.mask = SHADER_MASK_TEXTURE_ALPHA; + } else { + key.mask = SHADER_MASK_TEXTURE; + } } } else { key.mask = SHADER_MASK_NONE; @@ -539,7 +576,8 @@ glamor_composite_with_shader(CARD8 op, goto fail; } - if (key.source == SHADER_SOURCE_TEXTURE_ALPHA) { + 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) { @@ -553,7 +591,8 @@ glamor_composite_with_shader(CARD8 op, if (!good_source_format(source)) goto fail; } - if (key.mask == SHADER_MASK_TEXTURE_ALPHA) { + 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) { From 5360b1e8bbae571b120999e7eec7cd2826601497 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 09:47:38 -0800 Subject: [PATCH 080/462] glamor: Implement glCopyPixels based src == dest CopyArea acceleration --- glamor/glamor_copyarea.c | 117 +++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index f21752b42..578ad3087 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -32,18 +32,70 @@ * GC CopyArea implementation */ -void -glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, - Pixel bitplane, - void *closure) +static Bool +glamor_copy_n_to_n_copypixels(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy) +{ + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + int i; + + if (src != dst) { + glamor_fallback("glamor_copy_n_to_n_copypixels(): src != dest\n"); + return FALSE; + } + + if (gc) { + if (gc->alu != GXcopy) { + glamor_fallback("glamor_copy_n_to_n_copypixels(): non-copy ALU\n"); + return FALSE; + } + if (!glamor_pm_is_solid(dst, gc->planemask)) { + glamor_fallback("glamor_copy_n_to_n_copypixels(): " + "non-solid planemask\n"); + return FALSE; + } + } + + if (!glamor_set_destination_pixmap(dst_pixmap)) + return FALSE; + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glOrtho(0, dst_pixmap->drawable.width, + 0, dst_pixmap->drawable.height, + -1, 1); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + for (i = 0; i < nbox; i++) { + int flip_y1 = dst_pixmap->drawable.height - 1 - box[i].y2; + glRasterPos2i(box[i].x1 - dst_pixmap->screen_x, + flip_y1 - dst_pixmap->screen_x); + glCopyPixels(box[i].x1 + dx - src_pixmap->screen_x, + flip_y1 - dy - src_pixmap->screen_y, + box[i].x2 - box[i].x1, + box[i].y2 - box[i].y1, + GL_COLOR); + } + + return TRUE; +} + +static Bool +glamor_copy_n_to_n_textured(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy) { glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pScreen); @@ -116,22 +168,33 @@ glamor_copy_n_to_n(DrawablePtr src, glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); - -#if 0 - for (i = 0; i < nbox; i++) { - glRasterPos2i(box[i].x1 - dst_pixmap->screen_x, - box[i].y1 - dst_pixmap->screen_y); - glCopyPixels(box[i].x1 + dx - src_pixmap->screen_x, - box[i].y1 + dy - src_pixmap->screen_y, - box[i].x2 - box[i].x1, - box[i].y2 - box[i].y1, - GL_COLOR); - } -#endif - - return; + return TRUE; fail: + glamor_set_alu(GXcopy); + glamor_set_planemask(dst_pixmap, ~0); + return FALSE; +} + +void +glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)) + return; + + if (glamor_copy_n_to_n_textured(src, dst, gc, box, nbox, dx, dy)) + return; + glamor_fallback("glamor_copy_area() from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); @@ -144,8 +207,6 @@ fail: } glamor_finish_access(dst); } - glamor_set_alu(GXcopy); - glamor_set_planemask(dst_pixmap, ~0); } RegionPtr From be82a0624207b5f367b97c25ac7d7dbd8a518597 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 13:21:47 -0800 Subject: [PATCH 081/462] glamor: Fix screen_x/screen_y handling for compositing. It's not an offset from pixmap coords to composited pixmap coords, it's an offset from screen-relative window drawable coords to composited pixmap coords. --- glamor/glamor_copyarea.c | 37 ++++++++++++++++++++++--------------- glamor/glamor_core.c | 21 +++++++++++++++++++++ glamor/glamor_fill.c | 23 +++++++++++++---------- glamor/glamor_getspans.c | 7 +++++-- glamor/glamor_priv.h | 10 ++++++---- glamor/glamor_putimage.c | 5 ++++- glamor/glamor_render.c | 34 ++++++++++++++++++++++++++-------- glamor/glamor_setspans.c | 10 +++++++--- glamor/glamor_tile.c | 8 ++++---- 9 files changed, 108 insertions(+), 47 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 578ad3087..94e987ca2 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -41,9 +41,8 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, int dx, int dy) { - PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - int i; + int x_off, y_off, i; if (src != dst) { glamor_fallback("glamor_copy_n_to_n_copypixels(): src != dest\n"); @@ -74,12 +73,14 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, glMatrixMode(GL_PROJECTION); glLoadIdentity(); + glamor_get_drawable_deltas(dst, dst_pixmap, &x_off, &y_off); + for (i = 0; i < nbox; i++) { - int flip_y1 = dst_pixmap->drawable.height - 1 - box[i].y2; - glRasterPos2i(box[i].x1 - dst_pixmap->screen_x, - flip_y1 - dst_pixmap->screen_x); - glCopyPixels(box[i].x1 + dx - src_pixmap->screen_x, - flip_y1 - dy - src_pixmap->screen_y, + int flip_y1 = dst_pixmap->drawable.height - 1 - box[i].y2 + y_off; + glRasterPos2i(box[i].x1 + x_off, + flip_y1); + glCopyPixels(box[i].x1 + dx + x_off, + flip_y1 - dy, box[i].x2 - box[i].x1, box[i].y2 - box[i].y1, GL_COLOR); @@ -104,6 +105,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, int i; float vertices[4][2], texcoords[4][2]; glamor_pixmap_private *src_pixmap_priv; + int src_x_off, src_y_off, dst_x_off, dst_y_off; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); @@ -126,6 +128,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src, goto fail; } + 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; + dy += src_y_off; + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); glEnable(GL_TEXTURE_2D); @@ -143,14 +150,14 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glUseProgramObjectARB(glamor_priv->finish_access_prog); for (i = 0; i < nbox; i++) { - vertices[0][0] = v_from_x_coord_x(dst_pixmap, box[i].x1); - vertices[0][1] = v_from_x_coord_y(dst_pixmap, box[i].y1); - vertices[1][0] = v_from_x_coord_x(dst_pixmap, box[i].x2); - vertices[1][1] = v_from_x_coord_y(dst_pixmap, box[i].y1); - vertices[2][0] = v_from_x_coord_x(dst_pixmap, box[i].x2); - vertices[2][1] = v_from_x_coord_y(dst_pixmap, box[i].y2); - vertices[3][0] = v_from_x_coord_x(dst_pixmap, box[i].x1); - vertices[3][1] = v_from_x_coord_y(dst_pixmap, box[i].y2); + vertices[0][0] = v_from_x_coord_x(dst_pixmap, box[i].x1 + dst_x_off); + vertices[0][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); + vertices[1][0] = v_from_x_coord_x(dst_pixmap, box[i].x2 + dst_x_off); + vertices[1][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); + vertices[2][0] = v_from_x_coord_x(dst_pixmap, box[i].x2 + dst_x_off); + vertices[2][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); + vertices[3][0] = v_from_x_coord_x(dst_pixmap, box[i].x1 + dst_x_off); + vertices[3][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); texcoords[0][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); texcoords[0][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index b0a64f2ef..a4036c89e 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -52,6 +52,27 @@ glamor_get_drawable_location(const DrawablePtr drawable) 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) { diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 1b601ee5d..d2e8e8826 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -41,12 +41,15 @@ glamor_fill(DrawablePtr drawable, int height) { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); + int x_off, y_off; + + glamor_get_drawable_deltas(drawable, dst_pixmap, &x_off, &y_off); switch (gc->fillStyle) { case FillSolid: glamor_solid(dst_pixmap, - x - dst_pixmap->screen_x, - y - dst_pixmap->screen_y, + x + x_off, + y + y_off, width, height, gc->alu, @@ -57,28 +60,28 @@ glamor_fill(DrawablePtr drawable, case FillOpaqueStippled: glamor_stipple(dst_pixmap, gc->stipple, - x - dst_pixmap->screen_x, - y - dst_pixmap->screen_y, + x+ x_off, + y + y_off, width, height, gc->alu, gc->planemask, gc->fgPixel, gc->bgPixel, - gc->patOrg.x - dst_pixmap->screen_x, - gc->patOrg.y - dst_pixmap->screen_y); + gc->patOrg.x + x_off, + gc->patOrg.y + y_off); break; case FillTiled: glamor_tile(dst_pixmap, gc->tile.pixmap, - x - dst_pixmap->screen_x, - y - dst_pixmap->screen_y, + x + x_off, + y + y_off, width, height, gc->alu, gc->planemask, - gc->patOrg.x - dst_pixmap->screen_y, - gc->patOrg.y - dst_pixmap->screen_y); + gc->patOrg.x, + gc->patOrg.y); break; } } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 6e92b4d0b..92ffba5cc 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -55,6 +55,7 @@ glamor_get_spans(DrawablePtr drawable, GLenum format, type; int i, j; uint8_t *temp_dst = NULL, *readpixels_dst = (uint8_t *)dst; + int x_off, y_off; goto fail; @@ -86,9 +87,11 @@ glamor_get_spans(DrawablePtr drawable, if (!glamor_set_destination_pixmap(pixmap)) goto fail; + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + for (i = 0; i < count; i++) { - glReadPixels(points[i].x - pixmap->screen_x, - points[i].y - pixmap->screen_y, + glReadPixels(points[i].x + x_off, + points[i].y + y_off, widths[i], 1, format, type, diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 283f7ea12..c69ff98ec 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -200,25 +200,25 @@ glamor_fallback(char *format, ...) static inline float v_from_x_coord_x(PixmapPtr pixmap, int x) { - return (float)(x - pixmap->screen_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->screen_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->screen_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->screen_y) / pixmap->drawable.height; + return 1.0 - (float)y / pixmap->drawable.height; } /* glamor.c */ @@ -254,6 +254,8 @@ Bool glamor_prepare_access_gc(GCPtr gc); void glamor_finish_access_gc(GCPtr gc); void glamor_init_finish_access_shaders(ScreenPtr screen); const Bool glamor_get_drawable_location(const DrawablePtr drawable); +void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, + int *x, int *y); Bool glamor_create_gc(GCPtr gc); void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 537992101..b71644f02 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -244,6 +244,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int nbox; int bpp = drawable->bitsPerPixel; int src_stride = PixmapBytePad(w, drawable->depth); + int x_off, y_off; goto fail; @@ -297,6 +298,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, x += drawable->x; y += drawable->y; + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / bpp); if (bpp == 1) @@ -325,7 +328,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, continue; src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); - glRasterPos2i(x1 - pixmap->screen_x, y1 - pixmap->screen_y); + glRasterPos2i(x1 + x_off, y1 + y_off); glDrawPixels(x2 - x1, y2 - y1, format, type, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index cb9da1e1a..35e3e0a2b 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -533,6 +533,7 @@ glamor_composite_with_shader(CARD8 op, float vertices[4][2], source_texcoords[4][2], mask_texcoords[4][2]; int i; BoxPtr box; + int dst_x_off, dst_y_off; memset(&key, 0, sizeof(key)); if (!source->pDrawable) { @@ -673,16 +674,33 @@ glamor_composite_with_shader(CARD8 op, glEnableClientState(GL_TEXTURE_COORD_ARRAY); } + glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, + &dst_x_off, &dst_y_off); + if (source_pixmap) { + int dx, dy; + + glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &dx, &dy); + x_source += dx; + y_source += dy; + } + if (mask_pixmap) { + int dx, dy; + + glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &dx, &dy); + x_mask += dx; + y_mask += dy; + } + box = REGION_RECTS(®ion); for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { - vertices[0][0] = v_from_x_coord_x(dest_pixmap, box[i].x1); - vertices[0][1] = v_from_x_coord_y(dest_pixmap, box[i].y1); - vertices[1][0] = v_from_x_coord_x(dest_pixmap, box[i].x2); - vertices[1][1] = v_from_x_coord_y(dest_pixmap, box[i].y1); - vertices[2][0] = v_from_x_coord_x(dest_pixmap, box[i].x2); - vertices[2][1] = v_from_x_coord_y(dest_pixmap, box[i].y2); - vertices[3][0] = v_from_x_coord_x(dest_pixmap, box[i].x1); - vertices[3][1] = v_from_x_coord_y(dest_pixmap, box[i].y2); + vertices[0][0] = v_from_x_coord_x(dest_pixmap, box[i].x1 + dst_x_off); + vertices[0][1] = v_from_x_coord_y(dest_pixmap, box[i].y1 + dst_y_off); + vertices[1][0] = v_from_x_coord_x(dest_pixmap, box[i].x2 + dst_x_off); + vertices[1][1] = v_from_x_coord_y(dest_pixmap, box[i].y1 + dst_y_off); + vertices[2][0] = v_from_x_coord_x(dest_pixmap, box[i].x2 + dst_x_off); + vertices[2][1] = v_from_x_coord_y(dest_pixmap, box[i].y2 + dst_y_off); + vertices[3][0] = v_from_x_coord_x(dest_pixmap, box[i].x1 + dst_x_off); + vertices[3][1] = v_from_x_coord_y(dest_pixmap, box[i].y2 + dst_y_off); if (key.source != SHADER_SOURCE_SOLID) { int tx1 = box[i].x1 + x_source - x_dest; diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 32f7bc515..54aa26635 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -42,6 +42,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, int wmax = 0; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; + int x_off, y_off; goto fail; @@ -82,6 +83,9 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_set_alu(gc->alu); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; + + 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++) { @@ -98,12 +102,12 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (pbox->y1 > points[i].y) break; glScissor(pbox->x1, - points[i].y - dest_pixmap->screen_y, + points[i].y + y_off, pbox->x2 - pbox->x1, 1); glEnable(GL_SCISSOR_TEST); - glRasterPos2i(points[i].x - dest_pixmap->screen_x, - points[i].y - dest_pixmap->screen_y); + glRasterPos2i(points[i].x + x_off, + points[i].y + y_off); glDrawPixels(widths[i], 1, format, type, diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 517dbd3ea..01c4b7ab4 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -92,10 +92,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x2 = x + width; int y1 = y; int y2 = y + height; - int tile_x1 = tile_x - tile->screen_x; - int tile_x2 = tile_x - tile->screen_x + width; - int tile_y1 = tile_y - tile->screen_y; - int tile_y2 = tile_y - tile->screen_y + height; + int tile_x1 = tile_x; + int tile_x2 = tile_x + width; + int tile_y1 = tile_y; + int tile_y2 = tile_y + height; glamor_pixmap_private *tile_priv = glamor_get_pixmap_private(tile); if (glamor_priv->tile_prog == 0) { From 86a206525350b7e82ab0e432ad0fb8858960857d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 13:40:28 -0800 Subject: [PATCH 082/462] glamor: Fix off-by-one in CopyPixels CopyArea path. Fixes window dragging in uncomposited metacity. --- glamor/glamor_copyarea.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 94e987ca2..b7762cc22 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -76,7 +76,7 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &x_off, &y_off); for (i = 0; i < nbox; i++) { - int flip_y1 = dst_pixmap->drawable.height - 1 - box[i].y2 + y_off; + int flip_y1 = dst_pixmap->drawable.height - box[i].y2 + y_off; glRasterPos2i(box[i].x1 + x_off, flip_y1); glCopyPixels(box[i].x1 + dx + x_off, From d61a13cf3f0a3028fbcf41310a4f5ecaa8546961 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 14:52:04 -0800 Subject: [PATCH 083/462] glamor: Fix and enable tile fill acceleration (aka the root weave). --- glamor/glamor_fill.c | 4 +-- glamor/glamor_polyfillrect.c | 2 +- glamor/glamor_priv.h | 1 - glamor/glamor_tile.c | 66 +++++++++++++++++++++++------------- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index d2e8e8826..8e269e22e 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -80,8 +80,8 @@ glamor_fill(DrawablePtr drawable, height, gc->alu, gc->planemask, - gc->patOrg.x, - gc->patOrg.y); + drawable->x + x - gc->patOrg.x, + drawable->y + y - gc->patOrg.y); break; } } diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 62e0a0fe4..29e9db537 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -52,7 +52,7 @@ glamor_poly_fill_rect(DrawablePtr drawable, int xorg, yorg; int n; - if (gc->fillStyle != FillSolid) + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; xorg = drawable->x; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index c69ff98ec..91fa6e1fe 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -136,7 +136,6 @@ typedef struct glamor_screen_private { /* glamor_tile */ GLint tile_prog; - glamor_transform_uniforms tile_transform; /* glamor_putimage */ GLint put_image_xybitmap_prog; diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 01c4b7ab4..60a1a1e8f 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -41,17 +41,10 @@ glamor_init_tile_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); const char *tile_vs = - "uniform float x_bias;\n" - "uniform float x_scale;\n" - "uniform float y_bias;\n" - "uniform float y_scale;\n" "void main()\n" "{\n" - " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" - " (gl_Vertex.y + y_bias) * y_scale,\n" - " 0,\n" - " 1);\n" - " gl_TexCoord[0] = vec4(gl_MultiTexCoord0.xy, 0, 1);\n" + " gl_Position = gl_Vertex;\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" "}\n"; const char *tile_fs = "uniform sampler2D sampler;\n" @@ -76,8 +69,7 @@ glamor_init_tile_shader(ScreenPtr screen) glGetUniformLocationARB(glamor_priv->tile_prog, "sampler"); glUseProgramObjectARB(glamor_priv->tile_prog); glUniform1iARB(sampler_uniform_location, 0); - glamor_get_transform_uniform_locations(glamor_priv->tile_prog, - &glamor_priv->tile_transform); + glUseProgramObjectARB(0); } void @@ -97,6 +89,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int tile_y1 = tile_y; int tile_y2 = tile_y + height; 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) { ErrorF("Tiling unsupported\n"); @@ -105,32 +99,56 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (!glamor_set_destination_pixmap(pixmap)) goto fail; - if (tile_priv->fb == 0) { - ErrorF("Non-FBO tile pixmap\n"); + + if (tile_priv->tex == 0) { + ErrorF("Non-texture tile pixmap\n"); goto fail; } + if (!glamor_set_planemask(pixmap, planemask)) goto fail; glamor_set_alu(alu); + glUseProgramObjectARB(glamor_priv->tile_prog); - glamor_set_transform_for_pixmap(pixmap, &glamor_priv->tile_transform); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tile_priv->tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glEnable(GL_TEXTURE_2D); - glBegin(GL_TRIANGLE_FAN); - glMultiTexCoord2f(0, tile_x1, tile_y1); - glVertex2f(x1, y1); - glMultiTexCoord2f(0, tile_x1, tile_y2); - glVertex2f(x1, y2); - glMultiTexCoord2f(0, tile_x2, tile_y2); - glVertex2f(x2, y2); - glMultiTexCoord2f(0, tile_x2, tile_y1); - glVertex2f(x2, y1); - glEnd(); + vertices[0][0] = v_from_x_coord_x(pixmap, x1); + vertices[0][1] = v_from_x_coord_y(pixmap, y1); + vertices[1][0] = v_from_x_coord_x(pixmap, x2); + vertices[1][1] = v_from_x_coord_y(pixmap, y1); + vertices[2][0] = v_from_x_coord_x(pixmap, x2); + vertices[2][1] = v_from_x_coord_y(pixmap, y2); + vertices[3][0] = v_from_x_coord_x(pixmap, x1); + vertices[3][1] = v_from_x_coord_y(pixmap, y2); + + source_texcoords[0][0] = t_from_x_coord_x(tile, tile_x1); + source_texcoords[0][1] = t_from_x_coord_y(tile, tile_y1); + source_texcoords[1][0] = t_from_x_coord_x(tile, tile_x2); + source_texcoords[1][1] = t_from_x_coord_y(tile, tile_y1); + source_texcoords[2][0] = t_from_x_coord_x(tile, tile_x2); + source_texcoords[2][1] = t_from_x_coord_y(tile, tile_y2); + source_texcoords[3][0] = t_from_x_coord_x(tile, tile_x1); + source_texcoords[3][1] = t_from_x_coord_y(tile, tile_y2); + + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); glUseProgramObjectARB(0); glDisable(GL_TEXTURE_2D); From a63df0c504be3be0e969f5080a6593a55cb87246 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 15:00:32 -0800 Subject: [PATCH 084/462] glamor: Fix up the wide/non-solid lines fallback. --- glamor/glamor_polylines.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 48e62f454..5a7204b5e 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -52,13 +52,13 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0) { - ErrorF("stub wide polylines\n"); - return; + glamor_fallback("glamor_poly_lines(): wide lines\n"); + goto fail; } if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { - ErrorF("stub poly_line non-solid fill\n"); - return; + glamor_fallback("glamor_poly_lines(): non-solid fill\n"); + goto fail; } rects = xalloc(sizeof(xRectangle) * (n - 1)); @@ -104,4 +104,19 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, } gc->ops->PolyFillRect(drawable, gc, n - 1, rects); xfree(rects); + return; + +fail: + if (gc->lineWidth == 0) { + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access_gc(gc)) { + fbPolyLine(drawable, gc, mode, n, points); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); + } + return; + } + /* fb calls mi functions in the lineWidth != 0 case. */ + fbPolyLine(drawable, gc, mode, n, points); } From f88d76cf7e05cf885d80c0b91f37f1b30675e928 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 16:51:13 -0800 Subject: [PATCH 085/462] glamor: Enable glamor_fill_spans(). x11perf -wline100 performance goes from 8.8/sec to 111/sec. --- glamor/glamor_fillspans.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 9b070eced..a633b3066 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -45,7 +45,8 @@ glamor_fill_spans(DrawablePtr drawable, int fullX1, fullX2, fullY1; int partX1, partX2; - goto fail; + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) + goto fail; extents = REGION_EXTENTS(gc->pScreen, clip); extentX1 = extents->x1; @@ -101,7 +102,7 @@ glamor_fill_spans(DrawablePtr drawable, } return; fail: - glamor_fallback("to %p (%c)\n", drawable, + glamor_fallback("glamor_fillspans(): to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { From b1f67a5082420bbff141733833905f8ac95fe983 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 17:15:05 -0800 Subject: [PATCH 086/462] glamor: Fix and enable glamor_get_spans(). This makes running the cairo test suite almost tolerable. --- glamor/glamor_getspans.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 92ffba5cc..9b77f28db 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -57,8 +57,6 @@ glamor_get_spans(DrawablePtr drawable, uint8_t *temp_dst = NULL, *readpixels_dst = (uint8_t *)dst; int x_off, y_off; - goto fail; - switch (drawable->depth) { case 1: temp_dst = xalloc(wmax); @@ -71,9 +69,6 @@ glamor_get_spans(DrawablePtr drawable, 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; @@ -91,7 +86,7 @@ glamor_get_spans(DrawablePtr drawable, for (i = 0; i < count; i++) { glReadPixels(points[i].x + x_off, - points[i].y + y_off, + pixmap->drawable.height - 1 - (points[i].y + y_off), widths[i], 1, format, type, From 2ba634fab9b03995629497efdbf5305394011e4a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 11 Feb 2010 17:32:27 -0800 Subject: [PATCH 087/462] glamor: Fix render source transforms. Fixes (except for small bit differences) cairo source-pattern. --- glamor/glamor_render.c | 72 ++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 35e3e0a2b..6e281c910 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -508,6 +508,36 @@ good_dest_format(PicturePtr picture) } } +static inline float +xFixedToFloat(pixman_fixed_t val) +{ + 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; + + 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; + } + texcoord[0] = t_from_x_coord_x(pixmap, tx); + texcoord[1] = t_from_x_coord_y(pixmap, ty); +} + static Bool glamor_composite_with_shader(CARD8 op, PicturePtr source, @@ -707,29 +737,31 @@ glamor_composite_with_shader(CARD8 op, 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; - source_texcoords[0][0] = t_from_x_coord_x(source_pixmap, tx1); - source_texcoords[0][1] = t_from_x_coord_y(source_pixmap, ty1); - source_texcoords[1][0] = t_from_x_coord_x(source_pixmap, tx2); - source_texcoords[1][1] = t_from_x_coord_y(source_pixmap, ty1); - source_texcoords[2][0] = t_from_x_coord_x(source_pixmap, tx2); - source_texcoords[2][1] = t_from_x_coord_y(source_pixmap, ty2); - source_texcoords[3][0] = t_from_x_coord_x(source_pixmap, tx1); - source_texcoords[3][1] = t_from_x_coord_y(source_pixmap, ty2); + + glamor_set_transformed_point(source, source_pixmap, + source_texcoords[0], tx1, ty1); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords[1], tx2, ty1); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords[2], tx2, ty2); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords[3], tx1, ty2); } if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { - int tx1 = box[i].x1 + x_mask - x_dest; - int ty1 = box[i].y1 + y_mask - y_dest; - int tx2 = box[i].x2 + x_mask - x_dest; - int ty2 = box[i].y2 + y_mask - y_dest; - mask_texcoords[0][0] = t_from_x_coord_x(mask_pixmap, tx1); - mask_texcoords[0][1] = t_from_x_coord_y(mask_pixmap, ty1); - mask_texcoords[1][0] = t_from_x_coord_x(mask_pixmap, tx2); - mask_texcoords[1][1] = t_from_x_coord_y(mask_pixmap, ty1); - mask_texcoords[2][0] = t_from_x_coord_x(mask_pixmap, tx2); - mask_texcoords[2][1] = t_from_x_coord_y(mask_pixmap, ty2); - mask_texcoords[3][0] = t_from_x_coord_x(mask_pixmap, tx1); - mask_texcoords[3][1] = t_from_x_coord_y(mask_pixmap, ty2); + 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[1], tx2, ty1); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords[2], tx2, ty2); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords[3], tx1, ty2); } #if 0 else memset(mask_texcoords, 0, sizeof(mask_texcoords)); From 9bcbcbf8c28e945fa5c4f4ad1a772b787618455f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 17 Feb 2010 13:30:20 -0800 Subject: [PATCH 088/462] glamor: Fix and enable ZPixmap PutImage acceleration. --- glamor/glamor_putimage.c | 118 ++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index b71644f02..74910fa67 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -137,6 +137,9 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, 0.0, 1.0, }; + glamor_fallback("glamor_put_image_xybitmap: disabled\n"); + goto fail; + if (glamor_priv->put_image_xybitmap_prog == 0) { ErrorF("no program for xybitmap putimage\n"); goto fail; @@ -158,6 +161,7 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, glamor_set_transform_for_pixmap(pixmap, &glamor_priv->solid_transform); glGenTextures(1, &tex); + glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -237,7 +241,10 @@ void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int left_pad, int image_format, char *bits) { + 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); GLenum type, format; RegionPtr clip; BoxPtr pbox; @@ -245,14 +252,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int bpp = drawable->bitsPerPixel; int src_stride = PixmapBytePad(w, drawable->depth); int x_off, y_off; - - goto fail; - - if (!glamor_set_destination_pixmap(pixmap)) { - fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, - image_format, bits); - return; - } + float vertices[4][2], texcoords[4][2]; + GLuint tex; if (image_format == XYBitmap) { assert(depth == 1); @@ -261,13 +262,26 @@ 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 (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 (!glamor_set_planemask(pixmap, gc->planemask)) - goto fail; if (image_format != ZPixmap) { - ErrorF("putimage: non-ZPixmap\n"); + glamor_fallback("glamor_put_image: non-ZPixmap\n"); goto fail; } @@ -281,29 +295,57 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, type = GL_UNSIGNED_BYTE; break; case 24: - format = GL_RGB; - type = GL_UNSIGNED_BYTE; - break; + assert(drawable->bitsPerPixel == 32); + /* FALLTHROUGH */ case 32: format = GL_BGRA; type = GL_UNSIGNED_INT_8_8_8_8_REV; break; default: - ErrorF("stub put_image depth %d\n", drawable->depth); + glamor_fallback("glamor_putimage: bad depth %d\n", drawable->depth); goto fail; } + if (!glamor_set_planemask(pixmap, gc->planemask)) + goto fail; + glamor_set_alu(gc->alu); + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + + glClientActiveTexture(GL_TEXTURE0); + 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); + + 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + w, h, 0, + format, type, bits); + 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); + glUseProgramObjectARB(glamor_priv->finish_access_prog); + + x += drawable->x; y += drawable->y; glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / bpp); - if (bpp == 1) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); clip = fbGetCompositeClip(gc); for (nbox = REGION_NUM_RECTS(clip), pbox = REGION_RECTS(clip); @@ -314,7 +356,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int y1 = y; int x2 = x + w; int y2 = y + h; - char *src; + float src_x1, src_x2, src_y1, src_y2; if (x1 < pbox->x1) x1 = pbox->x1; @@ -327,13 +369,37 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (x1 >= x2 || y1 >= y2) continue; - src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); - glRasterPos2i(x1 + x_off, y1 + y_off); - glDrawPixels(x2 - x1, - y2 - y1, - format, type, - src); + src_x1 = (float)(x1 - x) / w; + src_y1 = (float)(y1 - y) / h; + src_x2 = (float)(x2 - x) / w; + src_y2 = (float)(y2 - y) / h; + + vertices[0][0] = v_from_x_coord_x(pixmap, x1 + x_off); + vertices[0][1] = v_from_x_coord_y(pixmap, y1 + y_off); + vertices[1][0] = v_from_x_coord_x(pixmap, x2 + x_off); + vertices[1][1] = v_from_x_coord_y(pixmap, y1 + y_off); + vertices[2][0] = v_from_x_coord_x(pixmap, x2 + x_off); + vertices[2][1] = v_from_x_coord_y(pixmap, y2 + y_off); + vertices[3][0] = v_from_x_coord_x(pixmap, x1 + x_off); + vertices[3][1] = v_from_x_coord_y(pixmap, y2 + y_off); + + texcoords[0][0] = src_x1; + texcoords[0][1] = src_y1; + texcoords[1][0] = src_x2; + texcoords[1][1] = src_y1; + texcoords[2][0] = src_x2; + texcoords[2][1] = src_y2; + texcoords[3][0] = src_x1; + texcoords[3][1] = src_y2; + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } + + glDisable(GL_TEXTURE_2D); + glUseProgramObjectARB(0); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDeleteTextures(1, &tex); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glamor_set_alu(GXcopy); From 2fa95725d845e5bf8a41ac776267be0d55d58004 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 17 Feb 2010 13:33:48 -0800 Subject: [PATCH 089/462] glamor: Add support for a1 composite sources. They're stored just like a8, but the values are set to either 0.0 or 1.0. Because they're a8 with only two legal values, we can't use them as destinations, but nobody's rendering to a1 dests anyway (we hope). --- glamor/glamor_render.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6e281c910..6d8dd9797 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -456,6 +456,7 @@ static Bool good_source_format(PicturePtr picture) { switch (picture->format) { + case PICT_a1: case PICT_a8: case PICT_a8r8g8b8: return TRUE; @@ -477,6 +478,7 @@ static Bool good_mask_format(PicturePtr picture) { switch (picture->format) { + case PICT_a1: case PICT_a8: case PICT_a8r8g8b8: return TRUE; From 5f5c35b56d3568f72e2305e74ed8457e0a787a3b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 17 Feb 2010 15:02:17 -0800 Subject: [PATCH 090/462] glamor: Fix up the fallback message for no texture present on compositing. --- glamor/glamor_render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6d8dd9797..421aa3530 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -618,7 +618,7 @@ glamor_composite_with_shader(CARD8 op, goto fail; } if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { - glamor_fallback("glamor_composite(): no FBO in source\n"); + glamor_fallback("glamor_composite(): no texture in source\n"); goto fail; } if (!good_source_format(source)) @@ -633,7 +633,7 @@ glamor_composite_with_shader(CARD8 op, goto fail; } if (!mask_pixmap_priv || mask_pixmap_priv->tex == 0) { - glamor_fallback("glamor_composite(): no FBO in mask\n"); + glamor_fallback("glamor_composite(): no texture in mask\n"); goto fail; } if (!good_mask_format(mask)) From 8cefa287ddb4ed4ad178e751b35bb93b4a44e0ab Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 17 Feb 2010 16:00:22 -0800 Subject: [PATCH 091/462] glamor: Add a little mechanism for only printing fallbacks when they happen. Sometimes we want to try a couple of different methods for accelerating. If one of them says "no" and the other says "yes", don't spam the log about the "no." --- glamor/glamor_copyarea.c | 21 +++++++++++++++------ glamor/glamor_priv.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index b7762cc22..172b9593c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -41,22 +41,25 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, int dx, int dy) { + ScreenPtr screen = dst->pScreen; PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int x_off, y_off, i; if (src != dst) { - glamor_fallback("glamor_copy_n_to_n_copypixels(): src != dest\n"); + glamor_delayed_fallback(screen, "glamor_copy_n_to_n_copypixels(): " + "src != dest\n"); return FALSE; } if (gc) { if (gc->alu != GXcopy) { - glamor_fallback("glamor_copy_n_to_n_copypixels(): non-copy ALU\n"); + glamor_delayed_fallback(screen, "glamor_copy_n_to_n_copypixels(): " + "non-copy ALU\n"); return FALSE; } if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_fallback("glamor_copy_n_to_n_copypixels(): " - "non-solid planemask\n"); + glamor_delayed_fallback(screen, "glamor_copy_n_to_n_copypixels(): " + "non-solid planemask\n"); return FALSE; } } @@ -196,11 +199,17 @@ glamor_copy_n_to_n(DrawablePtr src, Pixel bitplane, void *closure) { - if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)) + if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)) { + glamor_clear_delayed_fallbacks(dst->pScreen); return; + } - if (glamor_copy_n_to_n_textured(src, dst, gc, box, nbox, dx, dy)) + if (glamor_copy_n_to_n_textured(src, dst, gc, box, nbox, dx, dy)) { + glamor_clear_delayed_fallbacks(dst->pScreen); return; + } + + glamor_report_delayed_fallbacks(dst->pScreen); glamor_fallback("glamor_copy_area() from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 91fa6e1fe..cd7ca1528 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -126,6 +126,8 @@ typedef struct glamor_screen_private { CopyWindowProcPtr saved_copy_window; BitmapToRegionProcPtr saved_bitmap_to_region; + char *delayed_fallback_string; + /* glamor_finishaccess */ GLint finish_access_prog; @@ -196,6 +198,41 @@ glamor_fallback(char *format, ...) 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); + glamor_priv->delayed_fallback_string = XNFvprintf(format, ap); + va_end(ap); +} + +static inline void +glamor_clear_delayed_fallbacks(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + xfree(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, 0, "fallback: %s", + glamor_priv->delayed_fallback_string); + glamor_clear_delayed_fallbacks(screen); + } +} + static inline float v_from_x_coord_x(PixmapPtr pixmap, int x) { From d07fc66a056dd4eab2dac82b3784c482071d1915 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Feb 2010 09:23:22 -0800 Subject: [PATCH 092/462] glamor: Rework shader setup to make extending the IN types easier. --- glamor/glamor_priv.h | 9 +++- glamor/glamor_render.c | 107 ++++++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 44 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index cd7ca1528..5ce74890b 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -113,6 +113,12 @@ enum shader_mask { SHADER_MASK_COUNT, }; +enum shader_in { + SHADER_IN_SOURCE_ONLY, + SHADER_IN_NORMAL, + SHADER_IN_COUNT, +}; + typedef struct glamor_screen_private { CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; @@ -147,7 +153,8 @@ typedef struct glamor_screen_private { /* glamor_composite */ glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] - [SHADER_MASK_COUNT]; + [SHADER_MASK_COUNT] + [SHADER_IN_COUNT]; glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; } glamor_screen_private; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 421aa3530..f4840dc0c 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -41,6 +41,7 @@ struct shader_key { enum shader_source source; enum shader_mask mask; + enum shader_in in; }; struct blendinfo { @@ -69,51 +70,68 @@ static struct blendinfo composite_op_info[] = { static GLuint glamor_create_composite_fs(struct shader_key *key) { - const char *source_pixmap_header = - "uniform sampler2D source_sampler;\n"; - const char *source_solid_header = - "uniform vec4 source;\n"; - const char *mask_pixmap_header = - "uniform sampler2D mask_sampler;\n"; - const char *mask_solid_header = - "uniform vec4 mask;\n"; - const char *main_opening = - "void main()\n" - "{\n"; + const char *source_solid_fetch = + "uniform vec4 source;\n" + "vec4 get_source()\n" + "{\n" + " return source;\n" + "}\n"; const char *source_alpha_pixmap_fetch = - " vec4 source = texture2D(source_sampler, gl_TexCoord[0].xy);\n"; + "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 = - " vec4 source = vec4(texture2D(source_sampler, " - " gl_TexCoord[0].xy).rgb, 1.0);\n"; + "uniform sampler2D source_sampler;\n" + "vec4 get_source()\n" + "{\n" + " return vec4(texture2D(source_sampler, gl_TexCoord[0].xy).rgb,\n" + " 1.0);\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 = - " vec4 mask = texture2D(mask_sampler, gl_TexCoord[1].xy);\n"; + "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 = - " vec4 mask = vec4(texture2D(mask_sampler, " - " gl_TexCoord[1].xy).rgb, 1.0);\n"; - const char *source_in_mask = - " gl_FragColor = source * mask.a;\n"; - const char *source_only = - " gl_FragColor = source;\n"; - const char *main_closing = + "uniform sampler2D mask_sampler;\n" + "vec4 get_mask()\n" + "{\n" + " return vec4(texture2D(mask_sampler, gl_TexCoord[1].xy).rgb, \n" + " 1.0);\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"; char *source; - const char *source_setup = ""; - const char *source_fetch = ""; - const char *mask_setup = ""; + const char *source_fetch; const char *mask_fetch = ""; const char *in; GLuint prog; switch (key->source) { case SHADER_SOURCE_SOLID: - source_setup = source_solid_header; + source_fetch = source_solid_fetch; break; case SHADER_SOURCE_TEXTURE_ALPHA: - source_setup = source_pixmap_header; source_fetch = source_alpha_pixmap_fetch; break; case SHADER_SOURCE_TEXTURE: - source_setup = source_pixmap_header; source_fetch = source_pixmap_fetch; break; default: @@ -124,34 +142,33 @@ glamor_create_composite_fs(struct shader_key *key) case SHADER_MASK_NONE: break; case SHADER_MASK_SOLID: - mask_setup = mask_solid_header; + mask_fetch = mask_solid_fetch; break; case SHADER_MASK_TEXTURE_ALPHA: - mask_setup = mask_pixmap_header; mask_fetch = mask_alpha_pixmap_fetch; break; case SHADER_MASK_TEXTURE: - mask_setup = mask_pixmap_header; mask_fetch = mask_pixmap_fetch; break; default: FatalError("Bad composite shader mask"); } - if (key->mask == SHADER_MASK_NONE) { - in = source_only; - } else { - in = source_in_mask; + switch (key->in) { + case SHADER_IN_SOURCE_ONLY: + in = in_source_only; + break; + case SHADER_IN_NORMAL: + in = in_normal; + break; + default: + FatalError("Bad composite IN type"); } - source = XNFprintf("%s%s%s%s%s%s%s", - source_setup, - mask_setup, - main_opening, + source = XNFprintf("%s%s%s", source_fetch, mask_fetch, - in, - main_closing); + in); prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); xfree(source); @@ -245,7 +262,7 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_composite_shader *shader; - shader = &glamor_priv->composite_shader[key->source][key->mask]; + shader = &glamor_priv->composite_shader[key->source][key->mask][key->in]; if (shader->prog == 0) glamor_create_composite_shader(screen, key, shader); @@ -597,8 +614,11 @@ glamor_composite_with_shader(CARD8 op, key.mask = SHADER_MASK_TEXTURE; } } + + key.in = SHADER_IN_NORMAL; } else { key.mask = SHADER_MASK_NONE; + key.in = SHADER_IN_SOURCE_ONLY; } if (source->alphaMap) { glamor_fallback("source alphaMap\n"); @@ -851,6 +871,7 @@ glamor_composite(CARD8 op, width, height)) return; +fail: glamor_fallback("glamor_composite(): " "from picts %p/%p(%c,%c) to pict %p (%c)\n", source, mask, @@ -858,7 +879,7 @@ glamor_composite(CARD8 op, glamor_get_picture_location(mask), dest, glamor_get_picture_location(dest)); -fail: + glUseProgramObjectARB(0); glDisable(GL_BLEND); if (glamor_prepare_access(dest->pDrawable, GLAMOR_ACCESS_RW)) { From 858ce0c1928c199435c9c2627f84c37c7ca7a38a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Feb 2010 14:02:48 -0800 Subject: [PATCH 093/462] glamor: Add support for component alpha rendering. Brings x11perf -rgb24text from 230/sec to 18400/sec --- glamor/glamor_priv.h | 2 ++ glamor/glamor_render.c | 64 +++++++++++++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 5ce74890b..1b9740fa3 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -116,6 +116,8 @@ enum shader_mask { enum shader_in { SHADER_IN_SOURCE_ONLY, SHADER_IN_NORMAL, + SHADER_IN_CA_SOURCE, + SHADER_IN_CA_ALPHA, SHADER_IN_COUNT, }; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f4840dc0c..55d533856 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -118,6 +118,16 @@ glamor_create_composite_fs(struct shader_key *key) "{\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 = ""; @@ -161,6 +171,12 @@ glamor_create_composite_fs(struct shader_key *key) 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"); } @@ -615,11 +631,22 @@ glamor_composite_with_shader(CARD8 op, } } - key.in = SHADER_IN_NORMAL; + 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 { + assert(op == PictOpOutReverse); + key.in = SHADER_IN_CA_ALPHA; + } + } } else { key.mask = SHADER_MASK_NONE; key.in = SHADER_IN_SOURCE_ONLY; } + if (source->alphaMap) { glamor_fallback("source alphaMap\n"); goto fail; @@ -838,22 +865,25 @@ glamor_composite(CARD8 op, /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. */ - if (mask && mask->componentAlpha) - goto fail; - if (mask && mask->componentAlpha && 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; + 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) { From 6ce05e0b28052e5206694228218322f0dd3a6b00 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Feb 2010 14:44:20 -0800 Subject: [PATCH 094/462] glamor: Convert the shaders path to handling glamor_composite_rect_t. --- glamor/glamor_priv.h | 2 + glamor/glamor_render.c | 219 +++++++++++++++++++++++------------------ 2 files changed, 127 insertions(+), 94 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1b9740fa3..9a1640419 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -59,6 +59,8 @@ typedef struct 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; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 55d533856..45c7d9c69 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -578,18 +578,12 @@ glamor_composite_with_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, - INT16 y_dest, - CARD16 width, - CARD16 height) + int nrect, + glamor_composite_rect_t *rects) { ScreenPtr screen = dest->pDrawable->pScreen; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); - PixmapPtr source_pixmap, mask_pixmap = NULL; + 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; @@ -598,7 +592,9 @@ glamor_composite_with_shader(CARD8 op, float vertices[4][2], source_texcoords[4][2], mask_texcoords[4][2]; int i; BoxPtr box; - int dst_x_off, dst_y_off; + int dest_x_off, dest_y_off; + int source_x_off, source_y_off; + int mask_x_off, mask_y_off; memset(&key, 0, sizeof(key)); if (!source->pDrawable) { @@ -637,9 +633,11 @@ glamor_composite_with_shader(CARD8 op, /* We only handle two CA modes. */ if (op == PictOpAdd) key.in = SHADER_IN_CA_SOURCE; - else { - assert(op == PictOpOutReverse); + else if (op == PictOpOutReverse) { key.in = SHADER_IN_CA_ALPHA; + } else { + glamor_fallback("Unsupported component alpha op: %d\n", op); + goto fail; } } } else { @@ -705,17 +703,6 @@ glamor_composite_with_shader(CARD8 op, goto fail; } - 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 (key.source == SHADER_SOURCE_SOLID) { glamor_set_composite_solid(source, shader->source_uniform_location); } else { @@ -729,15 +716,6 @@ glamor_composite_with_shader(CARD8 op, } } - if (!miComputeCompositeRegion(®ion, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height)) - goto done; - - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -754,76 +732,124 @@ glamor_composite_with_shader(CARD8 op, } glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, - &dst_x_off, &dst_y_off); + &dest_x_off, &dest_y_off); if (source_pixmap) { - int dx, dy; - - glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &dx, &dy); - x_source += dx; - y_source += dy; + glamor_get_drawable_deltas(source->pDrawable, source_pixmap, + &source_x_off, &source_y_off); } if (mask_pixmap) { - int dx, dy; - - glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &dx, &dy); - x_mask += dx; - y_mask += dy; + glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, + &mask_x_off, &mask_y_off); } - box = REGION_RECTS(®ion); - for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { - vertices[0][0] = v_from_x_coord_x(dest_pixmap, box[i].x1 + dst_x_off); - vertices[0][1] = v_from_x_coord_y(dest_pixmap, box[i].y1 + dst_y_off); - vertices[1][0] = v_from_x_coord_x(dest_pixmap, box[i].x2 + dst_x_off); - vertices[1][1] = v_from_x_coord_y(dest_pixmap, box[i].y1 + dst_y_off); - vertices[2][0] = v_from_x_coord_x(dest_pixmap, box[i].x2 + dst_x_off); - vertices[2][1] = v_from_x_coord_y(dest_pixmap, box[i].y2 + dst_y_off); - vertices[3][0] = v_from_x_coord_x(dest_pixmap, box[i].x1 + dst_x_off); - vertices[3][1] = v_from_x_coord_y(dest_pixmap, box[i].y2 + dst_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; - 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; + 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; - glamor_set_transformed_point(source, source_pixmap, - source_texcoords[0], tx1, ty1); - glamor_set_transformed_point(source, source_pixmap, - source_texcoords[1], tx2, ty1); - glamor_set_transformed_point(source, source_pixmap, - source_texcoords[2], tx2, ty2); - glamor_set_transformed_point(source, source_pixmap, - source_texcoords[3], tx1, ty2); + 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 (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; + if (!miComputeCompositeRegion(®ion, + source, mask, dest, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height)) + continue; - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[0], tx1, ty1); - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[1], tx2, ty1); - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[2], tx2, ty2); - glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[3], tx1, ty2); - } + 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][0] = v_from_x_coord_x(dest_pixmap, + box[i].x1 + dest_x_off); + vertices[0][1] = v_from_x_coord_y(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[1][0] = v_from_x_coord_x(dest_pixmap, + box[i].x2 + dest_x_off); + vertices[1][1] = v_from_x_coord_y(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[2][0] = v_from_x_coord_x(dest_pixmap, + box[i].x2 + dest_x_off); + vertices[2][1] = v_from_x_coord_y(dest_pixmap, + box[i].y2 + dest_y_off); + vertices[3][0] = v_from_x_coord_x(dest_pixmap, + box[i].x1 + dest_x_off); + vertices[3][1] = 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[1], tx2, ty1); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords[2], tx2, ty2); + glamor_set_transformed_point(source, source_pixmap, + source_texcoords[3], 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[1], tx2, ty1); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords[2], tx2, ty2); + glamor_set_transformed_point(mask, mask_pixmap, + mask_texcoords[3], 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]); - } + 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 - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } + rects++; } glClientActiveTexture(GL_TEXTURE0); @@ -832,7 +858,6 @@ glamor_composite_with_shader(CARD8 op, glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); -done: REGION_UNINIT(dst->pDrawable->pScreen, ®ion); glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); @@ -862,6 +887,8 @@ glamor_composite(CARD8 op, CARD16 width, CARD16 height) { + glamor_composite_rect_t rect; + /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. */ @@ -894,11 +921,15 @@ glamor_composite(CARD8 op, return; } - if (glamor_composite_with_shader(op, source, mask, dest, - x_source, y_source, - x_mask, y_mask, - x_dest, y_dest, - width, height)) + 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: From 8ce312e61952e9f2193c28ac6124eff30f3a122c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Feb 2010 14:49:06 -0800 Subject: [PATCH 095/462] glamor: Use glamor_composite_with_shader once per group of glyphs. This shaves CPU time in GL setup. Performance of rgb24text went from 18400/sec to 23500/sec. --- glamor/glamor_render.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 45c7d9c69..e78886c56 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1113,6 +1113,9 @@ glamor_composite_rects(CARD8 op, ValidatePicture(src); ValidatePicture(dst); + if (glamor_composite_with_shader(op, src, NULL, dst, nrect, rects)) + return; + n = nrect; r = rects; From 60775e21e3532452891e1b52589f7d5d7ef04b40 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Feb 2010 18:11:54 -0800 Subject: [PATCH 096/462] glamor: Use a VBO to accumulate multiple glyph quads at once. This increases us from 23000 to 27000/sec on rgb24text. --- glamor/glamor_priv.h | 8 ++ glamor/glamor_render.c | 182 ++++++++++++++++++++++++++++++++--------- 2 files changed, 150 insertions(+), 40 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 9a1640419..0db9b28c4 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -138,6 +138,12 @@ typedef struct glamor_screen_private { char *delayed_fallback_string; + GLuint vbo; + int vbo_offset; + int vbo_size; + char *vb; + int vb_stride; + /* glamor_finishaccess */ GLint finish_access_prog; @@ -159,6 +165,8 @@ typedef struct glamor_screen_private { 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_screen_private; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e78886c56..de57f5219 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -573,6 +573,114 @@ glamor_set_transformed_point(PicturePtr picture, PixmapPtr pixmap, 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_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 *)(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_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 +glamor_emit_composite_vert(ScreenPtr screen, + const float *src_coords, + const float *mask_coords, + 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; + + 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; +} + +static void +glamor_flush_composite_rects(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + if (!glamor_priv->render_nr_verts) + return; + + 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; +} + +static void +glamor_emit_composite_rect(ScreenPtr screen, + const float *src_coords, + const float *mask_coords, + const float *dst_coords) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > + glamor_priv->vbo_size) + { + 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); + + 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); +} + static Bool glamor_composite_with_shader(CARD8 op, PicturePtr source, @@ -582,6 +690,7 @@ glamor_composite_with_shader(CARD8 op, 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; @@ -589,7 +698,7 @@ glamor_composite_with_shader(CARD8 op, struct shader_key key; glamor_composite_shader *shader; RegionRec region; - float vertices[4][2], source_texcoords[4][2], mask_texcoords[4][2]; + float vertices[8], source_texcoords[8], mask_texcoords[8]; int i; BoxPtr box; int dest_x_off, dest_y_off; @@ -716,20 +825,9 @@ glamor_composite_with_shader(CARD8 op, } } - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); - - if (key.source != SHADER_SOURCE_SOLID) { - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } - - if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { - glClientActiveTexture(GL_TEXTURE1); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, mask_texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } + 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); @@ -787,22 +885,22 @@ glamor_composite_with_shader(CARD8 op, box = REGION_RECTS(®ion); for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { - vertices[0][0] = v_from_x_coord_x(dest_pixmap, - box[i].x1 + dest_x_off); - vertices[0][1] = v_from_x_coord_y(dest_pixmap, - box[i].y1 + dest_y_off); - vertices[1][0] = v_from_x_coord_x(dest_pixmap, - box[i].x2 + dest_x_off); - vertices[1][1] = v_from_x_coord_y(dest_pixmap, - box[i].y1 + dest_y_off); - vertices[2][0] = v_from_x_coord_x(dest_pixmap, - box[i].x2 + dest_x_off); - vertices[2][1] = v_from_x_coord_y(dest_pixmap, - box[i].y2 + dest_y_off); - vertices[3][0] = v_from_x_coord_x(dest_pixmap, - box[i].x1 + dest_x_off); - vertices[3][1] = v_from_x_coord_y(dest_pixmap, - box[i].y2 + dest_y_off); + vertices[0] = v_from_x_coord_x(dest_pixmap, + box[i].x1 + dest_x_off); + vertices[1] = v_from_x_coord_y(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[2] = v_from_x_coord_x(dest_pixmap, + box[i].x2 + dest_x_off); + vertices[3] = v_from_x_coord_y(dest_pixmap, + box[i].y1 + dest_y_off); + vertices[4] = v_from_x_coord_x(dest_pixmap, + box[i].x2 + dest_x_off); + vertices[5] = v_from_x_coord_y(dest_pixmap, + box[i].y2 + dest_y_off); + vertices[6] = v_from_x_coord_x(dest_pixmap, + box[i].x1 + dest_x_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; @@ -811,13 +909,13 @@ glamor_composite_with_shader(CARD8 op, int ty2 = box[i].y2 + y_source - y_dest; glamor_set_transformed_point(source, source_pixmap, - source_texcoords[0], tx1, ty1); + source_texcoords + 0, tx1, ty1); glamor_set_transformed_point(source, source_pixmap, - source_texcoords[1], tx2, ty1); + source_texcoords + 2, tx2, ty1); glamor_set_transformed_point(source, source_pixmap, - source_texcoords[2], tx2, ty2); + source_texcoords + 4, tx2, ty2); glamor_set_transformed_point(source, source_pixmap, - source_texcoords[3], tx1, ty2); + source_texcoords + 6, tx1, ty2); } if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) { @@ -827,13 +925,13 @@ glamor_composite_with_shader(CARD8 op, float ty2 = box[i].y2 + y_mask - y_dest; glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[0], tx1, ty1); + mask_texcoords + 0, tx1, ty1); glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[1], tx2, ty1); + mask_texcoords + 2, tx2, ty1); glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[2], tx2, ty2); + mask_texcoords + 4, tx2, ty2); glamor_set_transformed_point(mask, mask_pixmap, - mask_texcoords[3], tx1, ty2); + mask_texcoords + 6, tx1, ty2); } #if 0 else memset(mask_texcoords, 0, sizeof(mask_texcoords)); @@ -847,11 +945,15 @@ glamor_composite_with_shader(CARD8 op, } #endif - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + 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); From 003dee4c82f8af9e7749876c736018410f347440 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 19 Feb 2010 06:10:11 -0800 Subject: [PATCH 097/462] glamor: Replace the immediate mode in glamor_fill() with glDrawArrays(). --- glamor/glamor_fill.c | 42 ++++++++++++++++------------------------ glamor/glamor_priv.h | 1 - glamor/glamor_putimage.c | 20 ++++++++++--------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 8e269e22e..c3e0528bf 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -92,29 +92,15 @@ glamor_init_solid_shader(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); const char *solid_vs_only = "uniform vec4 color;\n" - "uniform float x_bias;\n" - "uniform float x_scale;\n" - "uniform float y_bias;\n" - "uniform float y_scale;\n" "void main()\n" "{\n" - " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" - " (gl_Vertex.y + y_bias) * y_scale,\n" - " 0,\n" - " 1);\n" + " gl_Position = gl_Vertex;\n" " gl_Color = color;\n" "}\n"; const char *solid_vs = - "uniform float x_bias;\n" - "uniform float x_scale;\n" - "uniform float y_bias;\n" - "uniform float y_scale;\n" "void main()\n" "{\n" - " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" - " (gl_Vertex.y + y_bias) * y_scale,\n" - " 0,\n" - " 1);\n" + " gl_Position = gl_Vertex;\n" "}\n"; const char *solid_fs = "uniform vec4 color;\n" @@ -138,8 +124,6 @@ glamor_init_solid_shader(ScreenPtr screen) glamor_priv->solid_color_uniform_location = glGetUniformLocationARB(glamor_priv->solid_prog, "color"); - glamor_get_transform_uniform_locations(glamor_priv->solid_prog, - &glamor_priv->solid_transform); } void @@ -153,6 +137,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, int y1 = y; int y2 = y + height; GLfloat color[4]; + float vertices[4][2]; if (!glamor_set_destination_pixmap(pixmap)) return; @@ -163,15 +148,22 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color); - glamor_set_transform_for_pixmap(pixmap, &glamor_priv->solid_transform); - glBegin(GL_TRIANGLE_FAN); - glVertex2f(x1, y1); - glVertex2f(x1, y2); - glVertex2f(x2, y2); - glVertex2f(x2, y1); - glEnd(); + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + vertices[0][0] = v_from_x_coord_x(pixmap, x1); + vertices[0][1] = v_from_x_coord_y(pixmap, y1); + vertices[1][0] = v_from_x_coord_x(pixmap, x2); + vertices[1][1] = v_from_x_coord_y(pixmap, y1); + vertices[2][0] = v_from_x_coord_x(pixmap, x2); + vertices[2][1] = v_from_x_coord_y(pixmap, y2); + vertices[3][0] = v_from_x_coord_x(pixmap, x1); + vertices[3][1] = v_from_x_coord_y(pixmap, y2); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisableClientState(GL_VERTEX_ARRAY); glUseProgramObjectARB(0); fail: glamor_set_alu(GXcopy); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0db9b28c4..3dc3a5389 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -150,7 +150,6 @@ typedef struct glamor_screen_private { /* glamor_solid */ GLint solid_prog; GLint solid_color_uniform_location; - glamor_transform_uniforms solid_transform; /* glamor_tile */ GLint tile_prog; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 74910fa67..ead5b692e 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -124,12 +124,7 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, RegionPtr clip; BoxPtr box; int nbox; - float dest_coords[8] = { - x, y, - x + w, y, - x + w, y + h, - x, y + h, - }; + float dest_coords[4][2]; const float bitmap_coords[8] = { 0.0, 0.0, 1.0, 0.0, @@ -137,7 +132,16 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, 0.0, 1.0, }; - glamor_fallback("glamor_put_image_xybitmap: disabled\n"); + 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); + dest_coords[1][1] = v_from_x_coord_y(pixmap, y); + dest_coords[2][0] = v_from_x_coord_x(pixmap, x + w); + dest_coords[2][1] = v_from_x_coord_y(pixmap, y + h); + dest_coords[3][0] = v_from_x_coord_x(pixmap, x); + dest_coords[3][1] = v_from_x_coord_y(pixmap, y + h); + + glamor_fallback("glamor_put_image_xybitmap: disabled\n"); goto fail; if (glamor_priv->put_image_xybitmap_prog == 0) { @@ -158,8 +162,6 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, glUniform4fvARB(glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); - glamor_set_transform_for_pixmap(pixmap, &glamor_priv->solid_transform); - glGenTextures(1, &tex); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); From 955ccfbc34f370c80f7189ac5b0240e859e00b5f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 19 Feb 2010 07:52:50 -0800 Subject: [PATCH 098/462] glamor: Fix the segfault at screen fini. --- glamor/glamor.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 03db7ecec..b7259afa4 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -260,8 +260,10 @@ glamor_fini(ScreenPtr screen) screen->CopyWindow = glamor_priv->saved_copy_window; screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; #ifdef RENDER - ps->Composite = glamor_priv->saved_composite; - ps->Trapezoids = glamor_priv->saved_trapezoids; - ps->Glyphs = glamor_priv->saved_glyphs; + if (ps) { + ps->Composite = glamor_priv->saved_composite; + ps->Trapezoids = glamor_priv->saved_trapezoids; + ps->Glyphs = glamor_priv->saved_glyphs; + } #endif } From d2da9d1c22d25d1f86ecd83c15ca9909fab8610a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 19 Feb 2010 07:36:28 -0800 Subject: [PATCH 099/462] glamor: Reduce the noise from wide lines "fallback". --- glamor/glamor_polylines.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 5a7204b5e..acf6bf673 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -52,7 +52,10 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0) { - glamor_fallback("glamor_poly_lines(): wide lines\n"); + /* 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 || From 8cfcc614032320bb6a2eca2c61baeebf388d22ea Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 19 Feb 2010 07:14:13 -0800 Subject: [PATCH 100/462] glamor: Add support for using EXT_framebuffer_blit to do CopyArea. --- glamor/glamor_copyarea.c | 87 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 172b9593c..297a1fbc5 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -32,6 +32,88 @@ * GC CopyArea implementation */ +static Bool +glamor_copy_n_to_n_fbo_blit(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy) +{ + ScreenPtr screen = dst->pScreen; + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + glamor_pixmap_private *src_pixmap_priv; + 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"); + return FALSE; + } + + if (!GLEW_EXT_framebuffer_blit) { + glamor_delayed_fallback(screen, "glamor_copy_n_to_n_fbo_blit(): " + "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"); + 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"); + 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); + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); + src_y_off += dy; + + for (i = 0; i < nbox; i++) { + int flip_dst_y1 = dst_pixmap->drawable.height - (box[i].y2 + dst_y_off); + int flip_dst_y2 = dst_pixmap->drawable.height - (box[i].y1 + dst_y_off); + int flip_src_y1 = src_pixmap->drawable.height - (box[i].y2 + src_y_off); + int flip_src_y2 = src_pixmap->drawable.height - (box[i].y1 + src_y_off); + + glBlitFramebufferEXT(box[i].x1 + dx + src_x_off, + flip_src_y1, + box[i].x2 + dx + src_x_off, + flip_src_y2, + box[i].x1 + dst_x_off, + flip_dst_y1, + box[i].x2 + dst_x_off, + flip_dst_y2, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + } + + return TRUE; +} + static Bool glamor_copy_n_to_n_copypixels(DrawablePtr src, DrawablePtr dst, @@ -199,6 +281,11 @@ glamor_copy_n_to_n(DrawablePtr src, Pixel bitplane, void *closure) { + if (glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { + glamor_clear_delayed_fallbacks(dst->pScreen); + return; + } + if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)) { glamor_clear_delayed_fallbacks(dst->pScreen); return; From e194740c9413bbfefee6506a734e0c82c091dfa3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 8 Apr 2011 14:49:57 +0800 Subject: [PATCH 101/462] glamor: Fixed some compiling and linking errors. Change the inline functions to static type, otherwise when linking it complains multiple definitions of those functions. --- glamor/glu3/glu3.h | 4 +-- glamor/glu3/glu3_scalar.h | 52 +++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/glamor/glu3/glu3.h b/glamor/glu3/glu3.h index 29dba380a..27bcebc80 100644 --- a/glamor/glu3/glu3.h +++ b/glamor/glu3/glu3.h @@ -123,7 +123,7 @@ typedef struct GLUmat4Stack GLUmat4Stack; #ifdef __cplusplus extern "C" { #endif - +#if 0 GLfloat gluDot4_4v(const GLUvec4 *, const GLUvec4 *); GLfloat gluDot3_4v(const GLUvec4 *, const GLUvec4 *); GLfloat gluDot2_4v(const GLUvec4 *, const GLUvec4 *); @@ -169,7 +169,7 @@ void gluOrtho6f(GLUmat4 *result, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far); - +#endif extern const GLUmat4 gluIdentityMatrix; #ifdef __cplusplus diff --git a/glamor/glu3/glu3_scalar.h b/glamor/glu3/glu3_scalar.h index 3e87b8cce..00592f0dc 100644 --- a/glamor/glu3/glu3_scalar.h +++ b/glamor/glu3/glu3_scalar.h @@ -24,7 +24,7 @@ #include #include -extern inline void gluMult4v_4v(GLUvec4 *result, +static inline void gluMult4v_4v(GLUvec4 *result, const GLUvec4 *v1, const GLUvec4 *v2) { result->values[0] = v1->values[0] * v2->values[0]; @@ -34,7 +34,7 @@ extern inline void gluMult4v_4v(GLUvec4 *result, } -extern inline void gluDiv4v_4v(GLUvec4 *result, +static inline void gluDiv4v_4v(GLUvec4 *result, const GLUvec4 *v1, const GLUvec4 *v2) { result->values[0] = v1->values[0] / v2->values[0]; @@ -44,7 +44,7 @@ extern inline void gluDiv4v_4v(GLUvec4 *result, } -extern inline void gluAdd4v_4v(GLUvec4 *result, +static inline void gluAdd4v_4v(GLUvec4 *result, const GLUvec4 *v1, const GLUvec4 *v2) { result->values[0] = v1->values[0] + v2->values[0]; @@ -54,7 +54,7 @@ extern inline void gluAdd4v_4v(GLUvec4 *result, } -extern inline void gluSub4v_4v(GLUvec4 *result, +static inline void gluSub4v_4v(GLUvec4 *result, const GLUvec4 *v1, const GLUvec4 *v2) { result->values[0] = v1->values[0] - v2->values[0]; @@ -64,7 +64,7 @@ extern inline void gluSub4v_4v(GLUvec4 *result, } -extern inline void gluMult4v_f(GLUvec4 *result, +static inline void gluMult4v_f(GLUvec4 *result, const GLUvec4 *v1, GLfloat f) { result->values[0] = v1->values[0] * f; @@ -74,7 +74,7 @@ extern inline void gluMult4v_f(GLUvec4 *result, } -extern inline void gluDiv4v_f(GLUvec4 *result, +static inline void gluDiv4v_f(GLUvec4 *result, const GLUvec4 *v1, GLfloat f) { result->values[0] = v1->values[0] / f; @@ -84,7 +84,7 @@ extern inline void gluDiv4v_f(GLUvec4 *result, } -extern inline void gluAdd4v_f(GLUvec4 *result, +static inline void gluAdd4v_f(GLUvec4 *result, const GLUvec4 *v1, GLfloat f) { result->values[0] = v1->values[0] + f; @@ -94,7 +94,7 @@ extern inline void gluAdd4v_f(GLUvec4 *result, } -extern inline void gluSub4v_f(GLUvec4 *result, +static inline void gluSub4v_f(GLUvec4 *result, const GLUvec4 *v1, GLfloat f) { result->values[0] = v1->values[0] - f; @@ -104,7 +104,7 @@ extern inline void gluSub4v_f(GLUvec4 *result, } -extern inline void gluMult4m_f(GLUmat4 *result, +static inline void gluMult4m_f(GLUmat4 *result, const GLUmat4 *m, GLfloat f) { GLUmat4 temp; @@ -117,7 +117,7 @@ extern inline void gluMult4m_f(GLUmat4 *result, } -extern inline void gluMult4m_4v(GLUvec4 *result, +static inline void gluMult4m_4v(GLUvec4 *result, const GLUmat4 *m, const GLUvec4 *v) { GLUvec4 temp[6]; @@ -133,7 +133,7 @@ extern inline void gluMult4m_4v(GLUvec4 *result, } -extern inline void gluAdd4m_4m(GLUmat4 *result, +static inline void gluAdd4m_4m(GLUmat4 *result, const GLUmat4 *m1, const GLUmat4 *m2) { GLUmat4 temp; @@ -145,7 +145,7 @@ extern inline void gluAdd4m_4m(GLUmat4 *result, *result = temp; } -extern inline void gluSub4m_4m(GLUmat4 *result, +static inline void gluSub4m_4m(GLUmat4 *result, const GLUmat4 *m1, const GLUmat4 *m2) { GLUmat4 temp; @@ -157,7 +157,7 @@ extern inline void gluSub4m_4m(GLUmat4 *result, *result = temp; } -extern inline GLfloat gluDot4_4v(const GLUvec4 *v1, const GLUvec4 *v2) +static inline GLfloat gluDot4_4v(const GLUvec4 *v1, const GLUvec4 *v2) { return v1->values[0] * v2->values[0] + v1->values[1] * v2->values[1] @@ -166,7 +166,7 @@ extern inline GLfloat gluDot4_4v(const GLUvec4 *v1, const GLUvec4 *v2) } -extern inline GLfloat gluDot3_4v(const GLUvec4 *v1, const GLUvec4 *v2) +static inline GLfloat gluDot3_4v(const GLUvec4 *v1, const GLUvec4 *v2) { return v1->values[0] * v2->values[0] + v1->values[1] * v2->values[1] @@ -174,14 +174,14 @@ extern inline GLfloat gluDot3_4v(const GLUvec4 *v1, const GLUvec4 *v2) } -extern inline GLfloat gluDot2_4v(const GLUvec4 *v1, const GLUvec4 *v2) +static inline GLfloat gluDot2_4v(const GLUvec4 *v1, const GLUvec4 *v2) { return v1->values[0] * v2->values[0] + v1->values[1] * v2->values[1]; } -extern inline void gluCross4v(GLUvec4 *result, +static inline void gluCross4v(GLUvec4 *result, const GLUvec4 *v1, const GLUvec4 *v2) { GLUvec4 temp; @@ -197,7 +197,7 @@ extern inline void gluCross4v(GLUvec4 *result, } -extern inline void gluOuter4v(GLUmat4 *result, +static inline void gluOuter4v(GLUmat4 *result, const GLUvec4 *v1, const GLUvec4 *v2) { GLUmat4 temp; @@ -210,26 +210,26 @@ extern inline void gluOuter4v(GLUmat4 *result, } -extern inline GLfloat gluLengthSqr4v(const GLUvec4 *v) +static inline GLfloat gluLengthSqr4v(const GLUvec4 *v) { return gluDot4_4v(v, v); } -extern inline GLfloat gluLength4v(const GLUvec4 *v) +static inline GLfloat gluLength4v(const GLUvec4 *v) { return sqrt(gluLengthSqr4v(v)); } -extern inline void gluNormalize4v(GLUvec4 *result, const GLUvec4 *v) +static inline void gluNormalize4v(GLUvec4 *result, const GLUvec4 *v) { gluDiv4v_f(result, v, gluLength4v(v)); } -extern inline void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m) +static inline void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m) { unsigned i; unsigned j; @@ -245,7 +245,7 @@ extern inline void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m) } -extern inline void gluMult4m_4m(GLUmat4 *result, +static inline void gluMult4m_4m(GLUmat4 *result, const GLUmat4 *m1, const GLUmat4 *m2) { GLUmat4 temp; @@ -260,7 +260,7 @@ extern inline void gluMult4m_4m(GLUmat4 *result, -extern inline void gluTranslate3f(GLUmat4 *result, +static inline void gluTranslate3f(GLUmat4 *result, GLfloat x, GLfloat y, GLfloat z) { memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); @@ -271,7 +271,7 @@ extern inline void gluTranslate3f(GLUmat4 *result, #ifdef __cplusplus -extern inline GLfloat gluDot4(const GLUvec4 &v1, const GLUvec4 &v2) +static inline GLfloat gluDot4(const GLUvec4 &v1, const GLUvec4 &v2) { return v1.values[0] * v2.values[0] + v1.values[1] * v2.values[1] @@ -280,7 +280,7 @@ extern inline GLfloat gluDot4(const GLUvec4 &v1, const GLUvec4 &v2) } -extern inline GLfloat gluDot3(const GLUvec4 &v1, const GLUvec4 &v2) +static inline GLfloat gluDot3(const GLUvec4 &v1, const GLUvec4 &v2) { return v1.values[0] * v2.values[0] + v1.values[1] * v2.values[1] @@ -288,7 +288,7 @@ extern inline GLfloat gluDot3(const GLUvec4 &v1, const GLUvec4 &v2) } -extern inline GLfloat gluDot2(const GLUvec4 &v1, const GLUvec4 &v2) +static inline GLfloat gluDot2(const GLUvec4 &v1, const GLUvec4 &v2) { return v1.values[0] * v2.values[0] + v1.values[1] * v2.values[1]; From f9843c7a35975b178eec9812d21e1f02a2120928 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 8 Apr 2011 14:53:15 +0800 Subject: [PATCH 102/462] glamor: Fixed one conflict data type(XID) bug. We should include the dix-config.h for all the glamor files. Otherwise the XID type maybe inconsisitent in different files in 64bit machine. The root cause is this macro "#define _XSERVER64 1" should be included in all files refer to the data type "XID" which is originally defined in X.h. If _XSERVER64 is defined as 1, then XID is defined as CARD32 which is a 32bit integer. If _XSERVER64 is not defined as 1 then XID is "unsigned long". In a 32bit machine, "unsigned long" should be identical to CARD32. But in a 64bit machine, they are different. --- glamor/glamor_priv.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3dc3a5389..18bd76b12 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -24,10 +24,14 @@ * Eric Anholt * */ - #ifndef GLAMOR_PRIV_H #define GLAMOR_PRIV_H +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + + #include "glamor.h" #include From 3105fe9f6491f37a1f82a9e6f03f4efaed6c7e92 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 8 Apr 2011 15:22:52 +0800 Subject: [PATCH 103/462] glamor: Call glamor_composite_rects only when enable RENDER. --- glamor/glamor_glyphs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 7b2d13d0f..6e5595e68 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -572,8 +572,10 @@ glamor_buffer_glyph(ScreenPtr screen, 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 buffer->count = 0; buffer->source = NULL; From b3577a1c853d870f4d583a35d27012acb9099ef4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 8 Apr 2011 15:24:55 +0800 Subject: [PATCH 104/462] glamor: Merged with latest xserver. Merged with latest xserver, the major change is due to the API change of the management of devPrivates. --- glamor/glamor.c | 67 ++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index b7259afa4..29cefa8ec 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -30,17 +30,13 @@ * functions not responsible for performing rendering. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include #include "glamor_priv.h" -static int glamor_screen_private_key_index; +static DevPrivateKeyRec glamor_screen_private_key_index; DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index; -static int glamor_pixmap_private_key_index; +static DevPrivateKeyRec glamor_pixmap_private_key_index; DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index; /** @@ -68,54 +64,59 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { PixmapPtr pixmap; - glamor_pixmap_private *pixmap_priv; + glamor_pixmap_private *pixmap_priv, *newpixmap_priv; GLenum format; if (w > 32767 || h > 32767) return NullPixmap; 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); + assert(pixmap_priv != NULL); if (w == 0 || h == 0) return pixmap; - /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. * FBOs, which EXT_fbo forgot to do. */ switch (depth) { case 24: - format = GL_RGB; - break; + format = GL_RGB; + break; default: - format = GL_RGBA; - break; + format = GL_RGBA; + break; } + /* Create the texture used to store the pixmap's data. */ glGenTextures(1, &pixmap_priv->tex); glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); 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, format, w, h, 0, - format, GL_UNSIGNED_BYTE, NULL); + format, GL_UNSIGNED_BYTE, NULL); - /* Create a framebuffer object wrapping the texture so that we can render - * to it. - */ + /* Create a framebuffer object wrapping the texture so that we can render + ** to it. + **/ 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); + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, + pixmap_priv->tex, + 0); - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + screen->ModifyPixmapHeader(pixmap, w, h, depth, 0, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, NULL); - return pixmap; } @@ -156,13 +157,22 @@ glamor_init(ScreenPtr screen) if (glamor_priv == NULL) return FALSE; - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); - if (!dixRequestPrivate(glamor_pixmap_private_key, - sizeof(glamor_pixmap_private))) { + + if (!dixRegisterPrivateKey(glamor_screen_private_key,PRIVATE_SCREEN, + 0)) { LogMessage(X_WARNING, - "glamor%d: Failed to allocate pixmap private\n", + "glamor%d: Failed to allocate screen private\n", screen->myNum); } + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); + + if (!dixRegisterPrivateKey(glamor_pixmap_private_key,PRIVATE_PIXMAP, + sizeof(glamor_pixmap_private))) { + LogMessage(X_WARNING, + "glamor%d: Failed to allocate pixmap private\n", + screen->myNum); + } + glewInit(); @@ -224,16 +234,15 @@ glamor_init(ScreenPtr screen) ps->Trapezoids = glamor_trapezoids; glamor_priv->saved_glyphs = ps->Glyphs; ps->Glyphs = glamor_glyphs; + glamor_init_composite_shaders(screen); #endif - glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); glamor_init_putimage_shaders(screen); - glamor_init_composite_shaders(screen); glamor_init_finish_access_shaders(screen); - glamor_glyphs_init(screen); + return TRUE; fail: From 0d9e8db8d031d22b02df2c9b226287b1ca489f5a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 8 Apr 2011 15:30:45 +0800 Subject: [PATCH 105/462] glamor: Fixed one linking error. As current glamor implementation depends on the glx library in the mesa package which is conflict with the version in xorg. We have to --disable-glx when build Xephyr. But this leads to the linking error here. We comment out the calling to ephyrHijackGLXExtension() now. Need revisit latter. --- hw/kdrive/ephyr/ephyr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 1aacc5fe8..4bead1f36 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -669,7 +669,9 @@ ephyrInitScreen (ScreenPtr pScreen) } if (!ephyrNoDRI) { ephyrDRIExtensionInit (pScreen) ; +#if 0 ephyrHijackGLXExtension () ; +#endif } #endif From 47b6531273e3052b653194099a49ca11d80b12df Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 13 Apr 2011 15:50:26 +0800 Subject: [PATCH 106/462] glamor: Fixed one segfault bug when close screen. move the original glamor_fini to glamor_close_screen. And wrap the CloseScreen with glamor_close_screen, Then we can do some thing before call the underlying CloseScreen(). The root cause is that glamor_fini will be called after the ->CloseScreen(). This may trigger a segmentation fault at glamor_unrealize_glyph_caches() at calling into FreePicture(). --- glamor/glamor.c | 18 +++++++++++++++--- glamor/glamor_priv.h | 4 ++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 29cefa8ec..537fb685c 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -203,6 +203,9 @@ glamor_init(ScreenPtr screen) goto fail; } + glamor_priv->saved_close_screen = screen->CloseScreen; + screen->CloseScreen = glamor_close_screen; + glamor_priv->saved_create_gc = screen->CreateGC; screen->CreateGC = glamor_create_gc; @@ -251,8 +254,8 @@ fail: return FALSE; } -void -glamor_fini(ScreenPtr screen) +Bool +glamor_close_screen(int idx, ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); #ifdef RENDER @@ -260,7 +263,7 @@ glamor_fini(ScreenPtr screen) #endif glamor_glyphs_fini(screen); - + screen->CloseScreen = glamor_priv->saved_close_screen; screen->CreateGC = glamor_priv->saved_create_gc; screen->CreatePixmap = glamor_priv->saved_create_pixmap; screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; @@ -275,4 +278,13 @@ glamor_fini(ScreenPtr screen) ps->Glyphs = glamor_priv->saved_glyphs; } #endif + free(glamor_priv); + return screen->CloseScreen(idx, screen); + +} + +void +glamor_fini(ScreenPtr screen) +{ +/* Do nothing currently. */ } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 18bd76b12..c2f516d9c 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -128,6 +128,7 @@ enum shader_in { }; typedef struct glamor_screen_private { + CloseScreenProcPtr saved_close_screen; CreateGCProcPtr saved_create_gc; CreatePixmapProcPtr saved_create_pixmap; DestroyPixmapProcPtr saved_destroy_pixmap; @@ -282,6 +283,9 @@ t_from_x_coord_y(PixmapPtr pixmap, int y) /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); +Bool glamor_close_screen(int idx, ScreenPtr screen); + + /* glamor_copyarea.c */ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, From 49bf0e301e7317a02e8b34ec2e290fcfda520e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 5 Mar 2010 14:53:35 -0500 Subject: [PATCH 107/462] glamor ddx driver using EGL on KMS --- hw/xfree86/glamor/Makefile.am | 21 + hw/xfree86/glamor/glamor.c | 530 +++++++++++ hw/xfree86/glamor/glamor_crtc.c | 1493 +++++++++++++++++++++++++++++++ hw/xfree86/glamor/glamor_ddx.h | 15 + 4 files changed, 2059 insertions(+) create mode 100644 hw/xfree86/glamor/Makefile.am create mode 100644 hw/xfree86/glamor/glamor.c create mode 100644 hw/xfree86/glamor/glamor_crtc.c create mode 100644 hw/xfree86/glamor/glamor_ddx.h diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am new file mode 100644 index 000000000..4c82b42b8 --- /dev/null +++ b/hw/xfree86/glamor/Makefile.am @@ -0,0 +1,21 @@ +glamor_la_LTLIBRARIES = glamor.la +glamor_la_CFLAGS = \ + -DHAVE_XORG_CONFIG_H \ + @DIX_CFLAGS@ @XORG_CFLAGS@ \ + -I$(top_srcdir)/hw/xfree86/common \ + -I$(top_srcdir)/hw/xfree86/os-support/bus \ + -I$(top_srcdir)/hw/xfree86/parser \ + -I$(top_srcdir)/hw/xfree86/modes \ + -I$(top_srcdir)/hw/xfree86/ddc \ + -I$(top_srcdir)/hw/xfree86/ramdac \ + -I$(top_srcdir)/hw/xfree86/i2c \ + -I$(top_srcdir)/glamor \ + -I/usr/include/drm + +glamor_la_LDFLAGS = \ + -module -avoid-version -lEGL $(top_builddir)/glamor/libglamor.la -lGLEW +glamor_ladir = $(moduledir)/drivers +glamor_la_SOURCES = \ + glamor.c \ + glamor_crtc.c \ + glamor_ddx.h diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c new file mode 100644 index 000000000..b80d58758 --- /dev/null +++ b/hw/xfree86/glamor/glamor.c @@ -0,0 +1,530 @@ +/* + * Copyright © 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including + * the next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kristian Høgsberg + * + */ + +#include +#include +#include +#include + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#define EGL_DISPLAY_NO_X_MESA +#include +#include +#include + +#include "../../../mi/micmap.h" +#include +#include +#include + +#include "glamor_ddx.h" + +#define GLAMOR_VERSION_MAJOR 0 +#define GLAMOR_VERSION_MINOR 1 +#define GLAMOR_VERSION_PATCH 0 + +static const char glamor_name[] = "glamor"; + +static void +glamor_identify(int flags) +{ + xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver\n", glamor_name); +} + +struct glamor_screen_private { + EGLDisplay display; + EGLContext context; + EGLImageKHR root, cursor; + EGLint major, minor; + GLuint cursor_tex; + + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + int fd; + int cpp; +}; + +static inline struct glamor_screen_private * +glamor_get_screen_private(ScrnInfoPtr scrn) +{ + return (struct glamor_screen_private *) (scrn->driverPrivate); +} + +Bool +glamor_resize(ScrnInfoPtr scrn, int width, int height) +{ + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; + EGLImageKHR image; + GLuint texture; + EGLint attribs[] = { + EGL_IMAGE_WIDTH_INTEL, 0, + EGL_IMAGE_HEIGHT_INTEL, 0, + EGL_IMAGE_FORMAT_INTEL, EGL_FORMAT_RGBA_8888_KHR, + EGL_IMAGE_USE_INTEL, EGL_IMAGE_USE_SHARE_INTEL | + EGL_IMAGE_USE_SCANOUT_INTEL, + EGL_NONE + }; + + if (glamor->root != EGL_NO_IMAGE_KHR && + scrn->virtualX == width && scrn->virtualY == height) + return TRUE; + + attribs[1] = width; + attribs[3] = height; + image = eglCreateImageKHR(glamor->display, glamor->context, + EGL_SYSTEM_IMAGE_INTEL, + NULL, attribs); + if (image == EGL_NO_IMAGE_KHR) + return FALSE; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + 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->root = image; + scrn->virtualX = width; + scrn->virtualY = height; + + return TRUE; +} + +void +glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) +{ + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + EGLint name; + + eglShareImageINTEL (glamor->display, glamor->context, glamor->root, 0, + &name, (EGLint *) handle, (EGLint *) pitch); +} + +Bool +glamor_load_cursor(ScrnInfoPtr scrn, CARD32 *image, int width, int height) +{ + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + + if (glamor->cursor == NULL) { + EGLint attribs[] = { + EGL_IMAGE_WIDTH_INTEL, 0, + EGL_IMAGE_HEIGHT_INTEL, 0, + EGL_IMAGE_FORMAT_INTEL, EGL_FORMAT_RGBA_8888_KHR, + EGL_IMAGE_USE_INTEL, EGL_IMAGE_USE_SHARE_INTEL | + EGL_IMAGE_USE_SCANOUT_INTEL, + EGL_NONE + }; + + attribs[1] = width; + attribs[3] = height; + glamor->cursor = + eglCreateImageKHR(glamor->display, glamor->context, + EGL_SYSTEM_IMAGE_INTEL, + NULL, attribs); + if (image == EGL_NO_IMAGE_KHR) + return FALSE; + + glGenTextures(1, &glamor->cursor_tex); + glBindTexture(GL_TEXTURE_2D, glamor->cursor_tex); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, glamor->cursor); + } + + glBindTexture(GL_TEXTURE_2D, glamor->cursor_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image); + + return TRUE; +} + +void +glamor_cursor_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) +{ + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + EGLint name; + + eglShareImageINTEL (glamor->display, glamor->context, glamor->cursor, + 0, &name, (EGLint *) handle, (EGLint *) pitch); + ErrorF("cursor stride: %d\n", *pitch); +} + +static Bool +glamor_pre_init(ScrnInfoPtr scrn, int flags) +{ + struct glamor_screen_private *glamor; + rgb defaultWeight = { 0, 0, 0 }; + + glamor = xnfcalloc(sizeof *glamor, 1); + + scrn->driverPrivate = glamor; + + glamor->fd = open("/dev/dri/card0", O_RDWR); + glamor->cpp = 4; + + scrn->monitor = scrn->confScreen->monitor; + scrn->progClock = TRUE; + scrn->rgbBits = 8; + + if (!xf86SetDepthBpp(scrn, 0, 0, 0, Support32bppFb)) + return FALSE; + + xf86PrintDepthBpp(scrn); + + if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) + return FALSE; + if (!xf86SetDefaultVisual(scrn, -1)) + return FALSE; + + glamor->cpp = scrn->bitsPerPixel / 8; + + if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Kernel modesetting setup failed\n"); + xfree(glamor); + return FALSE; + } + + scrn->currentMode = scrn->modes; + xf86SetDpi(scrn, 0, 0); + + /* Load the required sub modules */ + if (!xf86LoadSubModule(scrn, "fb")) + return FALSE; + + return TRUE; +} + +static void +glamor_adjust_frame(int scrnIndex, int x, int y, int flags) +{ +} + +static Bool +glamor_enter_vt(int scrnIndex, int flags) +{ + ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + + if (drmSetMaster(glamor->fd)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "drmSetMaster failed: %s\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +static void +glamor_leave_vt(int scrnIndex, int flags) +{ + ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + + drmDropMaster(glamor->fd); +} + +static Bool +glamor_create_screen_resources(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + + screen->CreateScreenResources = glamor->CreateScreenResources; + if (!(*screen->CreateScreenResources) (screen)) + return FALSE; + + if (!xf86SetDesiredModes(scrn)) + return FALSE; + + return TRUE; +} + +static Bool +glamor_close_screen(int scrnIndex, ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + + if (scrn->vtSema == TRUE) + glamor_leave_vt(scrnIndex, 0); + + glamor_fini(screen); + + eglMakeCurrent(glamor->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate(glamor->display); + + drmmode_closefb(scrn); + + screen->CloseScreen = glamor->CloseScreen; + (*screen->CloseScreen) (scrnIndex, screen); + + return TRUE; +} + +static Bool +glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + EGLDisplayTypeDRMMESA display; + const char *version; + + display.type = EGL_DISPLAY_TYPE_DRM_MESA; + display.device = NULL; + display.fd = glamor->fd; + + glamor->display = eglGetDisplay((EGLNativeDisplayType) &display); + + if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "eglInitialize() failed\n"); + return FALSE; + } + + version = eglQueryString(glamor->display, EGL_VERSION); + xf86Msg(X_INFO, "%s: EGL version %s:", glamor_name, version); + + glamor->context = eglCreateContext(glamor->display, + NULL, EGL_NO_CONTEXT, NULL); + if (glamor->context == EGL_NO_CONTEXT) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to create EGL context\n"); + return FALSE; + } + if (!eglMakeCurrent(glamor->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, glamor->context)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make EGL context current\n"); + return FALSE; + } + + miClearVisualTypes(); + if (!miSetVisualTypes(scrn->depth, + miGetDefaultVisualMask(scrn->depth), + scrn->rgbBits, scrn->defaultVisual)) + return FALSE; + if (!miSetPixmapDepths()) + return FALSE; + + if (!fbScreenInit(screen, NULL, + scrn->virtualX, scrn->virtualY, + scrn->xDpi, scrn->yDpi, + 1, scrn->bitsPerPixel)) + return FALSE; + + fbPictureInit(screen, NULL, 0); + + xf86SetBlackWhitePixels(screen); + + if (!glamor_init(screen)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to initialize glamor\n"); + return FALSE; + } + + miInitializeBackingStore(screen); + xf86SetBackingStore(screen); + xf86SetSilkenMouse(screen); + miDCInitialize(screen, xf86GetPointerScreenFuncs()); + + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); + + if (!xf86_cursors_init(screen, 64, 64, + (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | + HARDWARE_CURSOR_ARGB))) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + } + + /* Must force it before EnterVT, so we are in control of VT and + * later memory should be bound when allocating, e.g rotate_mem */ + scrn->vtSema = TRUE; + + if (!glamor_enter_vt(scrnIndex, 0)) + return FALSE; + + screen->SaveScreen = xf86SaveScreen; + glamor->CreateScreenResources = screen->CreateScreenResources; + screen->CreateScreenResources = glamor_create_screen_resources; + glamor->CloseScreen = screen->CloseScreen; + screen->CloseScreen = glamor_close_screen; + + return TRUE; +} + +static void +glamor_free_screen(int scrnIndex, int flags) +{ + ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + + close(glamor->fd); + xfree(scrn->driverPrivate); + scrn->driverPrivate = NULL; +} + +static ModeStatus +glamor_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + if (mode->Flags & V_INTERLACE) { + if (verbose) { + xf86DrvMsg(scrnIndex, X_PROBED, + "Removing interlaced mode \"%s\"\n", + mode->name); + } + return MODE_BAD; + } + return MODE_OK; +} + +static Bool +glamor_probe(struct _DriverRec *drv, int flags) +{ + ScrnInfoPtr scrn = NULL; + GDevPtr *sections; + int entity, n; + + n = xf86MatchDevice(glamor_name, §ions); + if (n <= 0) + return FALSE; + + entity = xf86ClaimFbSlot(drv, 0, sections[0], TRUE); + + scrn = xf86ConfigFbEntity(scrn, 0, entity, NULL, NULL, NULL, NULL); + if (scrn == NULL) { + xf86Msg(X_ERROR, "Failed to add fb entity\n"); + return FALSE; + } + + scrn->driverVersion = 1; + scrn->driverName = (char *) glamor_name; + scrn->name = (char *) glamor_name; + scrn->Probe = NULL; + + scrn->PreInit = glamor_pre_init; + scrn->ScreenInit = glamor_screen_init; + scrn->AdjustFrame = glamor_adjust_frame; + scrn->EnterVT = glamor_enter_vt; + scrn->LeaveVT = glamor_leave_vt; + scrn->FreeScreen = glamor_free_screen; + scrn->ValidMode = glamor_valid_mode; + + return TRUE; +} + +static const OptionInfoRec * +glamor_available_options(int chipid, int busid) +{ + return NULL; +} + +static Bool +glamor_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) +{ + xorgHWFlags *flag; + + switch (op) { + case GET_REQUIRED_HW_INTERFACES: + flag = (CARD32*)ptr; + (*flag) = 0; + return TRUE; + default: + /* Unknown or deprecated function */ + return FALSE; + } +} + +_X_EXPORT DriverRec glamor = { + 1, + "glamor", + glamor_identify, + glamor_probe, + glamor_available_options, + NULL, + 0, + glamor_driver_func, +}; + +static pointer +glamor_setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = 0; + + /* This module should be loaded only once, but check to be sure. + */ + if (!setupDone) { + setupDone = 1; + xf86AddDriver(&glamor, module, HaveDriverFuncs); + + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer) 1; + } else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +static XF86ModuleVersionInfo glamor_version_info = { + glamor_name, + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + GLAMOR_VERSION_MAJOR, + GLAMOR_VERSION_MINOR, + GLAMOR_VERSION_PATCH, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData glamorModuleData = { + &glamor_version_info, + glamor_setup, + NULL +}; diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c new file mode 100644 index 000000000..4c9181922 --- /dev/null +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -0,0 +1,1493 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * Copyright © 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including + * the next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Dave Airlie + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "glamor_ddx.h" + +typedef struct { + int fd; + uint32_t fb_id; + drmModeResPtr mode_res; + int cpp; + + drmEventContext event_context; + void *event_data; + int old_fb_id; + int flip_count; +} drmmode_rec, *drmmode_ptr; + +typedef struct { + drmmode_ptr drmmode; + drmModeCrtcPtr mode_crtc; + uint32_t rotate_fb_id; + unsigned int cursor_tex; +} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; + +typedef struct { + drmModePropertyPtr mode_prop; + uint64_t value; + int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */ + Atom *atoms; +} drmmode_prop_rec, *drmmode_prop_ptr; + +struct fixed_panel_lvds { + int hdisplay; + int vdisplay; +}; +typedef struct { + drmmode_ptr drmmode; + int output_id; + drmModeConnectorPtr mode_output; + drmModeEncoderPtr mode_encoder; + drmModePropertyBlobPtr edid_blob; + int num_props; + drmmode_prop_ptr props; + void *private_data; + int dpms_mode; + char *backlight_iface; + int backlight_active_level; + int backlight_max; +} drmmode_output_private_rec, *drmmode_output_private_ptr; + +static void +drmmode_output_dpms(xf86OutputPtr output, int mode); +static Bool +drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height); + +#define BACKLIGHT_CLASS "/sys/class/backlight" + +/* + * List of available kernel interfaces in priority order + */ +static char *backlight_interfaces[] = { + "asus-laptop", + "eeepc", + "thinkpad_screen", + "acpi_video1", + "acpi_video0", + "fujitsu-laptop", + "sony", + "samsung", + NULL, +}; +/* + * Must be long enough for BACKLIGHT_CLASS + '/' + longest in above table + + * '/' + "max_backlight" + */ +#define BACKLIGHT_PATH_LEN 80 +/* Enough for 10 digits of backlight + '\n' + '\0' */ +#define BACKLIGHT_VALUE_LEN 12 + +static void +drmmode_backlight_set(xf86OutputPtr output, int level) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; + int fd, len, ret; + + if (level > drmmode_output->backlight_max) + level = drmmode_output->backlight_max; + if (! drmmode_output->backlight_iface || level < 0) + return; + + len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level); + sprintf(path, "%s/%s/brightness", + BACKLIGHT_CLASS, drmmode_output->backlight_iface); + fd = open(path, O_RDWR); + if (fd == -1) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s for backlight " + "control: %s\n", path, strerror(errno)); + return; + } + + ret = write(fd, val, len); + if (ret == -1) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "write to %s for backlight " + "control failed: %s\n", path, strerror(errno)); + } + + close(fd); +} + +static int +drmmode_backlight_get(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; + int fd, level; + + if (! drmmode_output->backlight_iface) + return -1; + + sprintf(path, "%s/%s/actual_brightness", + BACKLIGHT_CLASS, drmmode_output->backlight_iface); + fd = open(path, O_RDONLY); + if (fd == -1) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s " + "for backlight control: %s\n", path, strerror(errno)); + return -1; + } + + memset(val, 0, sizeof(val)); + if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) { + close(fd); + return -1; + } + + close(fd); + + level = atoi(val); + if (level > drmmode_output->backlight_max) + level = drmmode_output->backlight_max; + if (level < 0) + level = -1; + return level; +} + +static int +drmmode_backlight_get_max(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; + int fd, max = 0; + + sprintf(path, "%s/%s/max_brightness", + BACKLIGHT_CLASS, drmmode_output->backlight_iface); + fd = open(path, O_RDONLY); + if (fd == -1) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s " + "for backlight control: %s\n", path, strerror(errno)); + return 0; + } + + memset(val, 0, sizeof(val)); + if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) { + close(fd); + return -1; + } + + close(fd); + + max = atoi(val); + if (max <= 0) + max = -1; + return max; +} + +static void +drmmode_backlight_init(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + char path[BACKLIGHT_PATH_LEN]; + struct stat buf; + int i; + + for (i = 0; backlight_interfaces[i] != NULL; i++) { + sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]); + if (!stat(path, &buf)) { + drmmode_output->backlight_iface = backlight_interfaces[i]; + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, + "found backlight control interface %s\n", path); + drmmode_output->backlight_max = drmmode_backlight_get_max(output); + drmmode_output->backlight_active_level = drmmode_backlight_get(output); + return; + } + } + drmmode_output->backlight_iface = NULL; +} + + +static void +drmmode_ConvertFromKMode(ScrnInfoPtr scrn, + drmModeModeInfoPtr kmode, + DisplayModePtr mode) +{ + memset(mode, 0, sizeof(DisplayModeRec)); + mode->status = MODE_OK; + + mode->Clock = kmode->clock; + + mode->HDisplay = kmode->hdisplay; + mode->HSyncStart = kmode->hsync_start; + mode->HSyncEnd = kmode->hsync_end; + mode->HTotal = kmode->htotal; + mode->HSkew = kmode->hskew; + + mode->VDisplay = kmode->vdisplay; + mode->VSyncStart = kmode->vsync_start; + mode->VSyncEnd = kmode->vsync_end; + mode->VTotal = kmode->vtotal; + mode->VScan = kmode->vscan; + + mode->Flags = kmode->flags; //& FLAG_BITS; + mode->name = strdup(kmode->name); + + if (kmode->type & DRM_MODE_TYPE_DRIVER) + mode->type = M_T_DRIVER; + if (kmode->type & DRM_MODE_TYPE_PREFERRED) + mode->type |= M_T_PREFERRED; + xf86SetModeCrtc (mode, scrn->adjustFlags); +} + +static void +drmmode_ConvertToKMode(ScrnInfoPtr scrn, + drmModeModeInfoPtr kmode, + DisplayModePtr mode) +{ + memset(kmode, 0, sizeof(*kmode)); + + kmode->clock = mode->Clock; + kmode->hdisplay = mode->HDisplay; + kmode->hsync_start = mode->HSyncStart; + kmode->hsync_end = mode->HSyncEnd; + kmode->htotal = mode->HTotal; + kmode->hskew = mode->HSkew; + + kmode->vdisplay = mode->VDisplay; + kmode->vsync_start = mode->VSyncStart; + kmode->vsync_end = mode->VSyncEnd; + kmode->vtotal = mode->VTotal; + kmode->vscan = mode->VScan; + + kmode->flags = mode->Flags; //& FLAG_BITS; + if (mode->name) + strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); + kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; + +} + +static void +drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode) +{ + +} + +static Bool +drmmode_update_fb (ScrnInfoPtr scrn, int width, int height) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr + drmmode_crtc = xf86_config->crtc[0]->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + uint32_t handle, pitch; + int ret; + + if (drmmode->fb_id != 0 && + scrn->virtualX == width && scrn->virtualY == height) + return TRUE; + if (!glamor_resize(scrn, width, height)) + return FALSE; + if (drmmode->fb_id != 0) + drmModeRmFB(drmmode->fd, drmmode->fb_id); + glamor_frontbuffer_handle(scrn, &handle, &pitch); + ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, + scrn->bitsPerPixel, pitch * drmmode->cpp, + handle, &drmmode->fb_id); + if (ret) + /* FIXME: Undo glamor_resize() */ + return FALSE; + + return TRUE; +} + +static Bool +drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + int saved_x, saved_y; + Rotation saved_rotation; + DisplayModeRec saved_mode; + uint32_t *output_ids; + int output_count = 0; + int ret = TRUE; + int i; + int fb_id; + drmModeModeInfo kmode; + + if (!drmmode_update_fb(scrn, scrn->virtualX, scrn->virtualY)) + return FALSE; + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + + output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output); + if (!output_ids) { + ret = FALSE; + goto done; + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + drmmode_output_private_ptr drmmode_output; + + if (output->crtc != crtc) + continue; + + drmmode_output = output->driver_private; + output_ids[output_count] = + drmmode_output->mode_output->connector_id; + output_count++; + } + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0) + if (!xf86CrtcRotate(crtc, mode, rotation)) + goto done; +#else + if (!xf86CrtcRotate(crtc)) + goto done; +#endif + +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); +#endif + + drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); + + + fb_id = drmmode->fb_id; + if (drmmode_crtc->rotate_fb_id) { + fb_id = drmmode_crtc->rotate_fb_id; + x = 0; + y = 0; + } + ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + fb_id, x, y, output_ids, output_count, &kmode); + if (ret) + xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, + "failed to set mode: %s", strerror(-ret)); + else + ret = TRUE; + + /* Turn on any outputs on this crtc that may have been disabled */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + drmmode_output_dpms(output, DPMSModeOn); + } + + if (scrn->pScreen) + xf86_reload_cursors(scrn->pScreen); +done: + if (!ret) { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + } + return ret; +} + +static void +drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) +{ + +} + +static void +drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + ErrorF("move cursor\n"); + + drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); +} + +static void +drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) +{ + ScrnInfoPtr scrn = crtc->scrn; + + glamor_load_cursor(scrn, image, 64, 64); +} + + +static void +drmmode_hide_cursor (xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + 0, 64, 64); +} + +static void +drmmode_show_cursor (xf86CrtcPtr crtc) +{ + ScrnInfoPtr scrn = crtc->scrn; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + uint32_t handle, stride; + + ErrorF("show cursor\n"); + glamor_cursor_handle(scrn, &handle, &stride); + + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + handle, 64, 64); +} + +#if 0 +static void * +drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) +{ + ScrnInfoPtr scrn = crtc->scrn; + intel_screen_private *intel = intel_get_screen_private(scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + int size, ret; + unsigned long rotate_pitch; + + width = i830_pad_drawable_width(width, drmmode->cpp); + rotate_pitch = width * drmmode->cpp; + size = rotate_pitch * height; + + drmmode_crtc->rotate_bo = + drm_intel_bo_alloc(intel->bufmgr, "rotate", size, 4096); + + if (!drmmode_crtc->rotate_bo) { + xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + + drm_intel_bo_disable_reuse(drmmode_crtc->rotate_bo); + + ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, + crtc->scrn->bitsPerPixel, rotate_pitch, + drmmode_crtc->rotate_bo->handle, + &drmmode_crtc->rotate_fb_id); + if (ret) { + ErrorF("failed to add rotate fb\n"); + drm_intel_bo_unreference(drmmode_crtc->rotate_bo); + return NULL; + } + + return drmmode_crtc->rotate_bo; +} + +static PixmapPtr +drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + ScrnInfoPtr scrn = crtc->scrn; + intel_screen_private *intel = intel_get_screen_private(scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + + if (!data) { + data = drmmode_crtc_shadow_allocate (crtc, width, height); + if (!data) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + return NULL; + } + } + + rotate_pitch = + i830_pad_drawable_width(width, drmmode->cpp) * drmmode->cpp; + rotate_pixmap = GetScratchPixmapHeader(scrn->pScreen, + width, height, + scrn->depth, + scrn->bitsPerPixel, + rotate_pitch, + NULL); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + return NULL; + } + + if (drmmode_crtc->rotate_bo) + i830_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo); + + intel->shadow_present = TRUE; + + return rotate_pixmap; +} + +static void +drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ +} +#endif + +static void +drmmode_crtc_gamma_set(xf86CrtcPtr crtc, + CARD16 *red, CARD16 *green, CARD16 *blue, int size) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + size, red, green, blue); +} + +static const xf86CrtcFuncsRec drmmode_crtc_funcs = { + .dpms = drmmode_crtc_dpms, + .set_mode_major = drmmode_set_mode_major, + .set_cursor_colors = drmmode_set_cursor_colors, + .set_cursor_position = drmmode_set_cursor_position, + .show_cursor = drmmode_show_cursor, + .hide_cursor = drmmode_hide_cursor, + .load_cursor_argb = drmmode_load_cursor_argb, +#if 0 + .shadow_create = drmmode_crtc_shadow_create, + .shadow_allocate = drmmode_crtc_shadow_allocate, + .shadow_destroy = drmmode_crtc_shadow_destroy, +#endif + .gamma_set = drmmode_crtc_gamma_set, + .destroy = NULL, /* XXX */ +}; + + +static void +drmmode_crtc_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) +{ + xf86CrtcPtr crtc; + drmmode_crtc_private_ptr drmmode_crtc; + + crtc = xf86CrtcCreate(scrn, &drmmode_crtc_funcs); + if (crtc == NULL) + return; + + drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); + drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, + drmmode->mode_res->crtcs[num]); + drmmode_crtc->drmmode = drmmode; + crtc->driver_private = drmmode_crtc; + + return; +} + +static xf86OutputStatus +drmmode_output_detect(xf86OutputPtr output) +{ + /* go to the hw and retrieve a new output struct */ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmmode_ptr drmmode = drmmode_output->drmmode; + xf86OutputStatus status; + drmModeFreeConnector(drmmode_output->mode_output); + + drmmode_output->mode_output = + drmModeGetConnector(drmmode->fd, drmmode_output->output_id); + + switch (drmmode_output->mode_output->connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + break; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; + break; + default: + case DRM_MODE_UNKNOWNCONNECTION: + status = XF86OutputStatusUnknown; + break; + } + return status; +} + +static Bool +drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + struct fixed_panel_lvds *p_lvds = drmmode_output->private_data; + + /* + * If the connector type is LVDS, we will use the panel limit to + * verfiy whether the mode is valid. + */ + if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) { + if (pModes->HDisplay > p_lvds->hdisplay || + pModes->VDisplay > p_lvds->vdisplay) + return MODE_PANEL; + else + return MODE_OK; + } + return MODE_OK; +} + +static void fill_detailed_lvds_block(struct detailed_monitor_section *det_mon, + DisplayModePtr mode) +{ + struct detailed_timings *timing = &det_mon->section.d_timings; + + det_mon->type = DT; + timing->clock = mode->Clock * 1000; + timing->h_active = mode->HDisplay; + timing->h_blanking = mode->HTotal - mode->HDisplay; + timing->v_active = mode->VDisplay; + timing->v_blanking = mode->VTotal - mode->VDisplay; + timing->h_sync_off = mode->HSyncStart - mode->HDisplay; + timing->h_sync_width = mode->HSyncEnd - mode->HSyncStart; + timing->v_sync_off = mode->VSyncStart - mode->VDisplay; + timing->v_sync_width = mode->VSyncEnd - mode->VSyncStart; + + if (mode->Flags & V_PVSYNC) + timing->misc |= 0x02; + + if (mode->Flags & V_PHSYNC) + timing->misc |= 0x01; +} + +static int drmmode_output_lvds_edid(xf86OutputPtr output, + struct fixed_panel_lvds *p_lvds) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + int i, j; + DisplayModePtr pmode; + xf86MonPtr edid_mon; + drmModeModeInfo *mode_ptr; + struct detailed_monitor_section *det_mon; + + if (output->MonInfo) { + /* + * If there exists the EDID, we will either find a DS_RANGES + * or replace a DS_VENDOR block, smashing it into a DS_RANGES + * block with opern refresh to match all the default modes. + */ + int edid_det_block_num; + edid_mon = output->MonInfo; + edid_mon->features.msc |= 0x01; + j = -1; + edid_det_block_num = sizeof(edid_mon->det_mon) / + sizeof(edid_mon->det_mon[0]); + for (i = 0; i < edid_det_block_num; i++) { + if (edid_mon->det_mon[i].type >= DS_VENDOR && j == -1) + j = i; + if (edid_mon->det_mon[i].type == DS_RANGES) { + j = i; + break; + } + } + if (j != -1) { + struct monitor_ranges *ranges = + &edid_mon->det_mon[j].section.ranges; + edid_mon->det_mon[j].type = DS_RANGES; + ranges->min_v = 0; + ranges->max_v = 200; + ranges->min_h = 0; + ranges->max_h = 200; + } + return 0; + } + /* + * If there is no EDID, we will construct a bogus EDID for LVDS output + * device. This is similar to what we have done in i830_lvds.c + */ + edid_mon = NULL; + edid_mon = xcalloc(1, sizeof(xf86Monitor)); + if (!edid_mon) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "Can't allocate memory for edid_mon.\n"); + return 0; + } + /* Find the fixed panel mode. + * In theory when there is no EDID, KMS kernel will return only one + * mode. And this can be regarded as fixed lvds panel mode. + * But it will be better to traverse the mode list to get the fixed + * lvds panel mode again as we don't know whether some new modes + * are added for the LVDS output device + */ + j = 0; + for (i = 0; i < koutput->count_modes; i++) { + mode_ptr = &koutput->modes[i]; + if ((mode_ptr->hdisplay == p_lvds->hdisplay) && + (mode_ptr->vdisplay == p_lvds->vdisplay)) { + /* find the fixed panel mode */ + j = i; + break; + } + } + pmode = xnfalloc(sizeof(DisplayModeRec)); + drmmode_ConvertFromKMode(output->scrn, &koutput->modes[j], pmode); + /*support DPM, instead of DPMS*/ + edid_mon->features.dpms |= 0x1; + /*defaultly support RGB color display*/ + edid_mon->features.display_type |= 0x1; + /*defaultly display support continuous-freqencey*/ + edid_mon->features.msc |= 0x1; + /*defaultly the EDID version is 1.4 */ + edid_mon->ver.version = 1; + edid_mon->ver.revision = 4; + det_mon = edid_mon->det_mon; + if (pmode) { + /* now we construct new EDID monitor, + * so filled one detailed timing block + */ + fill_detailed_lvds_block(det_mon, pmode); + /* the filed timing block should be set preferred*/ + edid_mon->features.msc |= 0x2; + det_mon = det_mon + 1; + } + /* Set wide sync ranges so we get all modes + * handed to valid_mode for checking + */ + det_mon->type = DS_RANGES; + det_mon->section.ranges.min_v = 0; + det_mon->section.ranges.max_v = 200; + det_mon->section.ranges.min_h = 0; + det_mon->section.ranges.max_h = 200; + output->MonInfo = edid_mon; + return 0; +} + +static DisplayModePtr +drmmode_output_get_modes(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + int i; + DisplayModePtr Modes = NULL, Mode; + drmModePropertyPtr props; + struct fixed_panel_lvds *p_lvds; + drmModeModeInfo *mode_ptr; + + /* look for an EDID property */ + for (i = 0; i < koutput->count_props; i++) { + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + if (!props) + continue; + if (!(props->flags & DRM_MODE_PROP_BLOB)) { + drmModeFreeProperty(props); + continue; + } + + if (!strcmp(props->name, "EDID")) { + drmModeFreePropertyBlob(drmmode_output->edid_blob); + drmmode_output->edid_blob = + drmModeGetPropertyBlob(drmmode->fd, + koutput->prop_values[i]); + } + drmModeFreeProperty(props); + } + + if (drmmode_output->edid_blob) + xf86OutputSetEDID(output, + xf86InterpretEDID(output->scrn->scrnIndex, + drmmode_output->edid_blob->data)); + else + xf86OutputSetEDID(output, + xf86InterpretEDID(output->scrn->scrnIndex, + NULL)); + + /* modes should already be available */ + for (i = 0; i < koutput->count_modes; i++) { + Mode = xnfalloc(sizeof(DisplayModeRec)); + + drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], + Mode); + Modes = xf86ModesAdd(Modes, Mode); + + } + p_lvds = drmmode_output->private_data; + /* + * If the connector type is LVDS, we will traverse the kernel mode to + * get the panel limit. + * If it is incorrect, please fix me. + */ + if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) { + p_lvds->hdisplay = 0; + p_lvds->vdisplay = 0; + for (i = 0; i < koutput->count_modes; i++) { + mode_ptr = &koutput->modes[i]; + if ((mode_ptr->hdisplay >= p_lvds->hdisplay) && + (mode_ptr->vdisplay >= p_lvds->vdisplay)) { + p_lvds->hdisplay = mode_ptr->hdisplay; + p_lvds->vdisplay = mode_ptr->vdisplay; + } + } + if (!p_lvds->hdisplay || !p_lvds->vdisplay) + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "Incorrect KMS mode.\n"); + drmmode_output_lvds_edid(output, p_lvds); + } + return Modes; +} + +static void +drmmode_output_destroy(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + int i; + + if (drmmode_output->edid_blob) + drmModeFreePropertyBlob(drmmode_output->edid_blob); + for (i = 0; i < drmmode_output->num_props; i++) { + drmModeFreeProperty(drmmode_output->props[i].mode_prop); + xfree(drmmode_output->props[i].atoms); + } + xfree(drmmode_output->props); + drmModeFreeConnector(drmmode_output->mode_output); + if (drmmode_output->private_data) { + xfree(drmmode_output->private_data); + drmmode_output->private_data = NULL; + } + if (drmmode_output->backlight_iface) + drmmode_backlight_set(output, drmmode_output->backlight_active_level); + xfree(drmmode_output); + output->driver_private = NULL; +} + +static void +drmmode_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + + if (!drmmode_output->backlight_iface) + return; + + if (mode == DPMSModeOn) { + /* If we're going from off->on we may need to turn on the backlight. */ + if (oldmode != DPMSModeOn) + drmmode_backlight_set(output, drmmode_output->backlight_active_level); + } else { + /* Only save the current backlight value if we're going from on to off. */ + if (oldmode == DPMSModeOn) + drmmode_output->backlight_active_level = drmmode_backlight_get(output); + drmmode_backlight_set(output, 0); + } +} + +static void +drmmode_output_dpms(xf86OutputPtr output, int mode) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + int i; + drmModePropertyPtr props; + + for (i = 0; i < koutput->count_props; i++) { + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + if (!props) + continue; + + if (!strcmp(props->name, "DPMS")) { + drmModeConnectorSetProperty(drmmode->fd, + drmmode_output->output_id, + props->prop_id, + mode); + drmmode_output_dpms_backlight(output, + drmmode_output->dpms_mode, + mode); + drmmode_output->dpms_mode = mode; + drmModeFreeProperty(props); + return; + } + drmModeFreeProperty(props); + } +} + +static Bool +drmmode_property_ignore(drmModePropertyPtr prop) +{ + if (!prop) + return TRUE; + /* ignore blob prop */ + if (prop->flags & DRM_MODE_PROP_BLOB) + return TRUE; + /* ignore standard property */ + if (!strcmp(prop->name, "EDID") || + !strcmp(prop->name, "DPMS")) + return TRUE; + + return FALSE; +} + +#define BACKLIGHT_NAME "Backlight" +#define BACKLIGHT_DEPRECATED_NAME "BACKLIGHT" +static Atom backlight_atom, backlight_deprecated_atom; + +static void +drmmode_output_create_resources(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr mode_output = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + drmModePropertyPtr drmmode_prop; + int i, j, err; + + drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec)); + if (!drmmode_output->props) + return; + + drmmode_output->num_props = 0; + for (i = 0, j = 0; i < mode_output->count_props; i++) { + drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]); + if (drmmode_property_ignore(drmmode_prop)) { + drmModeFreeProperty(drmmode_prop); + continue; + } + drmmode_output->props[j].mode_prop = drmmode_prop; + drmmode_output->props[j].value = mode_output->prop_values[i]; + drmmode_output->num_props++; + j++; + } + + for (i = 0; i < drmmode_output->num_props; i++) { + drmmode_prop_ptr p = &drmmode_output->props[i]; + drmmode_prop = p->mode_prop; + + if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { + INT32 range[2]; + + p->num_atoms = 1; + p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); + if (!p->atoms) + continue; + p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); + range[0] = drmmode_prop->values[0]; + range[1] = drmmode_prop->values[1]; + err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], + FALSE, TRUE, + drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, + 2, range); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + err = RRChangeOutputProperty(output->randr_output, p->atoms[0], + XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { + p->num_atoms = drmmode_prop->count_enums + 1; + p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); + if (!p->atoms) + continue; + p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); + for (j = 1; j <= drmmode_prop->count_enums; j++) { + struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; + p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); + } + err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], + FALSE, FALSE, + drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, + p->num_atoms - 1, (INT32 *)&p->atoms[1]); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + for (j = 0; j < drmmode_prop->count_enums; j++) + if (drmmode_prop->enums[j].value == p->value) + break; + /* there's always a matching value */ + err = RRChangeOutputProperty(output->randr_output, p->atoms[0], + XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + } + + if (drmmode_output->backlight_iface) { + INT32 data, backlight_range[2]; + /* Set up the backlight property, which takes effect immediately + * and accepts values only within the backlight_range. */ + backlight_atom = MakeAtom(BACKLIGHT_NAME, sizeof(BACKLIGHT_NAME) - 1, TRUE); + backlight_deprecated_atom = MakeAtom(BACKLIGHT_DEPRECATED_NAME, + sizeof(BACKLIGHT_DEPRECATED_NAME) - 1, TRUE); + + backlight_range[0] = 0; + backlight_range[1] = drmmode_output->backlight_max; + err = RRConfigureOutputProperty(output->randr_output, backlight_atom, + FALSE, TRUE, FALSE, 2, backlight_range); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + err = RRConfigureOutputProperty(output->randr_output, backlight_deprecated_atom, + FALSE, TRUE, FALSE, 2, backlight_range); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + data = drmmode_output->backlight_active_level; + err = RRChangeOutputProperty(output->randr_output, backlight_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + err = RRChangeOutputProperty(output->randr_output, backlight_deprecated_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } +} + +static Bool +drmmode_output_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmmode_ptr drmmode = drmmode_output->drmmode; + int i; + + if (property == backlight_atom || property == backlight_deprecated_atom) { + INT32 val; + + if (value->type != XA_INTEGER || value->format != 32 || + value->size != 1) + { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < 0 || val > drmmode_output->backlight_max) + return FALSE; + + if (drmmode_output->dpms_mode == DPMSModeOn) + drmmode_backlight_set(output, val); + drmmode_output->backlight_active_level = val; + return TRUE; + } + + for (i = 0; i < drmmode_output->num_props; i++) { + drmmode_prop_ptr p = &drmmode_output->props[i]; + + if (p->atoms[0] != property) + continue; + + if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { + uint32_t val; + + if (value->type != XA_INTEGER || value->format != 32 || + value->size != 1) + return FALSE; + val = *(uint32_t *)value->data; + + drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, + p->mode_prop->prop_id, (uint64_t)val); + return TRUE; + } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { + Atom atom; + const char *name; + int j; + + if (value->type != XA_ATOM || value->format != 32 || value->size != 1) + return FALSE; + memcpy(&atom, value->data, 4); + name = NameForAtom(atom); + + /* search for matching name string, then set its value down */ + for (j = 0; j < p->mode_prop->count_enums; j++) { + if (!strcmp(p->mode_prop->enums[j].name, name)) { + drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, + p->mode_prop->prop_id, p->mode_prop->enums[j].value); + return TRUE; + } + } + return FALSE; + } + } + + return TRUE; +} + +static Bool +drmmode_output_get_property(xf86OutputPtr output, Atom property) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + int err; + + if (property == backlight_atom || property == backlight_deprecated_atom) { + INT32 val; + + if (! drmmode_output->backlight_iface) + return FALSE; + + val = drmmode_backlight_get(output); + if (val < 0) + return FALSE; + err = RRChangeOutputProperty(output->randr_output, property, + XA_INTEGER, 32, PropModeReplace, 1, &val, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + return FALSE; + } + + return TRUE; + } + + return TRUE; +} + +static const xf86OutputFuncsRec drmmode_output_funcs = { + .create_resources = drmmode_output_create_resources, +#ifdef RANDR_12_INTERFACE + .set_property = drmmode_output_set_property, + .get_property = drmmode_output_get_property, +#endif + .dpms = drmmode_output_dpms, + .detect = drmmode_output_detect, + .mode_valid = drmmode_output_mode_valid, + + .get_modes = drmmode_output_get_modes, + .destroy = drmmode_output_destroy +}; + +static int subpixel_conv_table[7] = { 0, SubPixelUnknown, + SubPixelHorizontalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalRGB, + SubPixelVerticalBGR, + SubPixelNone }; + +static const char *output_names[] = { "None", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "TV", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", +}; + + +static void +drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) +{ + xf86OutputPtr output; + drmModeConnectorPtr koutput; + drmModeEncoderPtr kencoder; + drmmode_output_private_ptr drmmode_output; + char name[32]; + + koutput = drmModeGetConnector(drmmode->fd, + drmmode->mode_res->connectors[num]); + if (!koutput) + return; + + kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]); + if (!kencoder) { + drmModeFreeConnector(koutput); + return; + } + + snprintf(name, 32, "%s%d", output_names[koutput->connector_type], + koutput->connector_type_id); + + output = xf86OutputCreate (scrn, &drmmode_output_funcs, name); + if (!output) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + + drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1); + if (!drmmode_output) { + xf86OutputDestroy(output); + drmModeFreeConnector(koutput); + drmModeFreeEncoder(kencoder); + return; + } + /* + * If the connector type of the output device is LVDS, we will + * allocate the private_data to store the panel limit. + * For example: hdisplay, vdisplay + */ + drmmode_output->private_data = NULL; + if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) { + drmmode_output->private_data = xcalloc( + sizeof(struct fixed_panel_lvds), 1); + if (!drmmode_output->private_data) + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Can't allocate private memory for LVDS.\n"); + } + drmmode_output->output_id = drmmode->mode_res->connectors[num]; + drmmode_output->mode_output = koutput; + drmmode_output->mode_encoder = kencoder; + drmmode_output->drmmode = drmmode; + output->mm_width = koutput->mmWidth; + output->mm_height = koutput->mmHeight; + + output->subpixel_order = subpixel_conv_table[koutput->subpixel]; + output->driver_private = drmmode_output; + + if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) + drmmode_backlight_init(output); + + output->possible_crtcs = kencoder->possible_crtcs; + output->possible_clones = kencoder->possible_clones; + return; +} + + +static Bool +drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + + if (!drmmode_update_fb(scrn, width, height)) + return FALSE; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if (!crtc->enabled) + continue; + + drmmode_set_mode_major(crtc, &crtc->mode, + crtc->rotation, crtc->x, crtc->y); + } + + return TRUE; +} + +static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { + drmmode_xf86crtc_resize +}; + +#if 0 +Bool +drmmode_do_pageflip(ScreenPtr screen, dri_bo *new_front, dri_bo *old_front, + void *data) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + unsigned int pitch = scrn->displayWidth * intel->cpp; + int i, old_fb_id; + unsigned int crtc_id; + + /* + * Create a new handle for the back buffer + */ + old_fb_id = drmmode->fb_id; + if (drmModeAddFB(drmmode->fd, scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, pitch, + new_front->handle, &drmmode->fb_id)) + goto error_out; + + /* + * Queue flips on all enabled CRTCs + * Note that if/when we get per-CRTC buffers, we'll have to update this. + * Right now it assumes a single shared fb across all CRTCs, with the + * kernel fixing up the offset of each CRTC as necessary. + * + * Also, flips queued on disabled or incorrectly configured displays + * may never complete; this is a configuration error. + */ + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + + if (!crtc->enabled) + continue; + + drmmode_crtc = crtc->driver_private; + crtc_id = drmmode_crtc->mode_crtc->crtc_id; + drmmode->event_data = data; + drmmode->flip_count++; + if (drmModePageFlip(drmmode->fd, crtc_id, drmmode->fb_id, + DRM_MODE_PAGE_FLIP_EVENT, drmmode)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed: %s\n", strerror(errno)); + goto error_undo; + } + } + + dri_bo_pin(new_front, 0); + dri_bo_unpin(new_front); + + scrn->fbOffset = new_front->offset; + intel->front_buffer->bo = new_front; + intel->front_buffer->offset = new_front->offset; + drmmode->old_fb_id = old_fb_id; + + return TRUE; + +error_undo: + drmModeRmFB(drmmode->fd, drmmode->fb_id); + drmmode->fb_id = old_fb_id; + +error_out: + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", + strerror(errno)); + return FALSE; +} + +static void +drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event_data); +} + +static void +drmmode_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + drmmode_ptr drmmode = event_data; + + drmmode->flip_count--; + if (drmmode->flip_count > 0) + return; + + drmModeRmFB(drmmode->fd, drmmode->old_fb_id); + + I830DRI2FlipEventHandler(frame, tv_sec, tv_usec, drmmode->event_data); +} + +static void +drm_wakeup_handler(pointer data, int err, pointer p) +{ + drmmode_ptr drmmode = data; + fd_set *read_mask = p; + + if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) + drmHandleEvent(drmmode->fd, &drmmode->event_context); +} +#endif + +Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp) +{ + drmmode_ptr drmmode; + unsigned int i; + + drmmode = xnfalloc(sizeof *drmmode); + drmmode->fd = fd; + drmmode->fb_id = 0; + + xf86CrtcConfigInit(scrn, &drmmode_xf86crtc_config_funcs); + + drmmode->cpp = cpp; + drmmode->mode_res = drmModeGetResources(drmmode->fd); + if (!drmmode->mode_res) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "failed to get resources: %s\n", strerror(errno)); + return FALSE; + } + + xf86CrtcSetSizeRange(scrn, 320, 200, drmmode->mode_res->max_width, + drmmode->mode_res->max_height); + for (i = 0; i < drmmode->mode_res->count_crtcs; i++) + drmmode_crtc_init(scrn, drmmode, i); + + for (i = 0; i < drmmode->mode_res->count_connectors; i++) + drmmode_output_init(scrn, drmmode, i); + + xf86InitialConfiguration(scrn, TRUE); + +#if 0 + gp.param = I915_PARAM_HAS_PAGEFLIPPING; + gp.value = &has_flipping; + (void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, + sizeof(gp)); + if (has_flipping) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Kernel page flipping support detected, enabling\n"); + intel->use_pageflipping = TRUE; + drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; + drmmode->event_context.vblank_handler = drmmode_vblank_handler; + drmmode->event_context.page_flip_handler = + drmmode_page_flip_handler; + AddGeneralSocket(fd); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + drm_wakeup_handler, drmmode); + } +#endif + + return TRUE; +} + +void drmmode_closefb(ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr xf86_config; + drmmode_crtc_private_ptr drmmode_crtc; + drmmode_ptr drmmode; + + xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + + drmmode_crtc = xf86_config->crtc[0]->driver_private; + drmmode = drmmode_crtc->drmmode; + + drmModeRmFB(drmmode->fd, drmmode->fb_id); + drmmode->fb_id = 0; +} diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h new file mode 100644 index 000000000..0968f013f --- /dev/null +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -0,0 +1,15 @@ +#ifndef GLAMOR_DDX_H +#define GLAMOR_DDX_H + +Bool glamor_resize(ScrnInfoPtr scrn, int width, int height); +void glamor_frontbuffer_handle(ScrnInfoPtr scrn, + uint32_t *handle, uint32_t *pitch); +Bool glamor_load_cursor(ScrnInfoPtr scrn, + CARD32 *image, int width, int height); +void glamor_cursor_handle(ScrnInfoPtr scrn, + uint32_t *handle, uint32_t *pitch); + +Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); +void drmmode_closefb(ScrnInfoPtr scrn); + +#endif From 26ff612171d53baef08078a852875d5ddf1804ed Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 11 May 2011 15:54:50 +0800 Subject: [PATCH 108/462] glamor: Resolved merge conflictions with Kristian's glamor-ddx patch. --- configure.ac | 1 + glamor/glamor.c | 58 ++++++++++++++++++++++------------ glamor/glamor.h | 2 ++ hw/xfree86/common/xf86pciBus.c | 2 +- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 7a8e507e7..caefc4674 100644 --- a/configure.ac +++ b/configure.ac @@ -2185,6 +2185,7 @@ hw/xfree86/utils/Makefile hw/xfree86/utils/man/Makefile hw/xfree86/utils/cvt/Makefile hw/xfree86/utils/gtf/Makefile +hw/xfree86/glamor/Makefile hw/dmx/config/Makefile hw/dmx/config/man/Makefile hw/dmx/doc/Makefile diff --git a/glamor/glamor.c b/glamor/glamor.c index 537fb685c..b5252aacf 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -59,25 +59,54 @@ glamor_get_drawable_pixmap(DrawablePtr drawable) return (PixmapPtr)drawable; } + +void +glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_pixmap_private *pixmap_priv; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv->tex = tex; + + /* Create a framebuffer object wrapping the texture so that we can render + * to it. + */ + 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); + + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + (((w * pixmap->drawable.bitsPerPixel + + 7) / 8) + 3) & ~3, + NULL); +} + + + static PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { PixmapPtr pixmap; - glamor_pixmap_private *pixmap_priv, *newpixmap_priv; GLenum format; + GLuint tex; + if (w > 32767 || h > 32767) return NullPixmap; 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); - assert(pixmap_priv != NULL); if (w == 0 || h == 0) return pixmap; @@ -95,28 +124,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, /* Create the texture used to store the pixmap's data. */ - glGenTextures(1, &pixmap_priv->tex); - glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + glGenTextures(1, &tex); + 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); glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); - /* Create a framebuffer object wrapping the texture so that we can render - ** to it. - **/ - 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); + glamor_set_pixmap_texture(pixmap, w, h, tex); - screen->ModifyPixmapHeader(pixmap, w, h, depth, 0, - (((w * pixmap->drawable.bitsPerPixel + - 7) / 8) + 3) & ~3, - NULL); return pixmap; } @@ -149,6 +165,7 @@ Bool glamor_init(ScreenPtr screen) { glamor_screen_private *glamor_priv; + #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif @@ -173,7 +190,6 @@ glamor_init(ScreenPtr screen) screen->myNum); } - glewInit(); if (!GLEW_EXT_framebuffer_object) { @@ -196,13 +212,13 @@ glamor_init(ScreenPtr screen) ErrorF("GL_EXT_bgra required\n"); goto fail; } - if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, NULL)) { goto fail; } + glamor_priv->saved_close_screen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; diff --git a/glamor/glamor.h b/glamor/glamor.h index 50617b857..546a50c42 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -37,5 +37,7 @@ #endif /* GLAMOR_H */ + Bool glamor_init(ScreenPtr screen); void glamor_fini(ScreenPtr screen); +void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex); diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index 447b19229..56fb62f64 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1118,7 +1118,7 @@ videoPtrToDriverList(struct pci_device *dev, } else if (dev->device_id == 0x8108) { break; /* "hooray" for poulsbo */ } else { - driverList[0] = "intel"; + driverList[0] = "glamor"; } break; case 0x102b: driverList[0] = "mga"; break; From 6dae8dc7ea6e7add3c6fda30773f264904ef8df5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 11 May 2011 15:57:05 +0800 Subject: [PATCH 109/462] glamor: Add glamor-ddx driver to the build tree. Correct the linking parameters and add dependency to the libglamor.a. --- hw/xfree86/Makefile.am | 4 ++-- hw/xfree86/glamor/Makefile.am | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am index e3ef14fc1..830f17ac9 100644 --- a/hw/xfree86/Makefile.am +++ b/hw/xfree86/Makefile.am @@ -27,12 +27,12 @@ if INT10MODULE INT10_SUBDIR = int10 endif -SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw os-support parser \ +SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw glamor os-support parser \ ramdac shadowfb $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \ loader dixmods exa modes \ $(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) doc man -DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \ +DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw glamor os-support \ parser ramdac shadowfb vbe vgahw xaa \ loader dixmods dri dri2 exa modes \ utils doc man diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index 4c82b42b8..d691009eb 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -13,9 +13,12 @@ glamor_la_CFLAGS = \ -I/usr/include/drm glamor_la_LDFLAGS = \ - -module -avoid-version -lEGL $(top_builddir)/glamor/libglamor.la -lGLEW + -module -avoid-version -L$(libdir) -lEGL $(top_builddir)/glamor/libglamor.la -lGLEW glamor_ladir = $(moduledir)/drivers glamor_la_SOURCES = \ glamor.c \ glamor_crtc.c \ glamor_ddx.h + +glamor_la_DEPENDENCIES = \ + $(top_builddir)/glamor/libglamor.la From eb3487a448ff0efa46079323821d65d7c3e4d872 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 12 May 2011 01:08:38 +0800 Subject: [PATCH 110/462] glamor: Add new feature which is to flip output on y axis. Due to the coordinate system on EGL is different from FBO object. To support EGL surface well, we add this new feature. When calling glamor_init from EGL ddx driver, it should use the new flag GLAMOR_INVERTED_Y_AXIS. --- glamor/glamor.c | 11 ++++++- glamor/glamor.h | 5 ++- glamor/glamor_copyarea.c | 56 +++++++++++++++++++++++++++++----- glamor/glamor_core.c | 34 +++++++++++++++++---- glamor/glamor_fill.c | 17 ++++++++--- glamor/glamor_getspans.c | 11 +++++++ glamor/glamor_priv.h | 16 +++++++++- glamor/glamor_putimage.c | 20 +++++++++--- glamor/glamor_render.c | 33 +++++++++++++++----- glamor/glamor_tile.c | 31 +++++++++++++------ hw/kdrive/ephyr/ephyr_glamor.c | 2 +- 11 files changed, 193 insertions(+), 43 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index b5252aacf..026f1bf52 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -162,10 +162,15 @@ glamor_wakeup_handler(void *data, int result, void *last_select_mask) /** Set up glamor for an already-configured GL context. */ Bool -glamor_init(ScreenPtr screen) +glamor_init(ScreenPtr screen, unsigned int flags) { glamor_screen_private *glamor_priv; + if (flags & ~GLAMOR_VALID_FLAGS) { + ErrorF("glamor_init: Invalid flags %x\n", flags); + return FALSE; + } + #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif @@ -174,6 +179,10 @@ glamor_init(ScreenPtr screen) if (glamor_priv == NULL) return FALSE; + if (flags & GLAMOR_INVERTED_Y_AXIS) { + glamor_priv->yInverted = 1; + } else + glamor_priv->yInverted = 0; if (!dixRegisterPrivateKey(glamor_screen_private_key,PRIVATE_SCREEN, 0)) { diff --git a/glamor/glamor.h b/glamor/glamor.h index 546a50c42..33610a668 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -38,6 +38,9 @@ #endif /* GLAMOR_H */ -Bool glamor_init(ScreenPtr screen); +#define GLAMOR_INVERTED_Y_AXIS 0x1 +#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS) + +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); diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 297a1fbc5..07d8b1456 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -45,6 +45,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); glamor_pixmap_private *src_pixmap_priv; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int dst_x_off, dst_y_off, src_x_off, src_y_off, i; if (src == dst) { @@ -94,6 +95,18 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, src_y_off += dy; for (i = 0; i < nbox; i++) { + if(glamor_priv->yInverted) { + glBlitFramebufferEXT((box[i].x1 + dx + src_x_off), + (box[i].y1 + src_y_off), + (box[i].x2 + dx + src_x_off), + (box[i].y2 + src_y_off), + (box[i].x1 + dst_x_off), + (box[i].y1 + dst_y_off), + (box[i].x2 + dst_x_off), + (box[i].y2 + dst_y_off), + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + } else { int flip_dst_y1 = dst_pixmap->drawable.height - (box[i].y2 + dst_y_off); int flip_dst_y2 = dst_pixmap->drawable.height - (box[i].y1 + dst_y_off); int flip_src_y1 = src_pixmap->drawable.height - (box[i].y2 + src_y_off); @@ -109,6 +122,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, flip_dst_y2, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } } return TRUE; @@ -125,6 +139,8 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, { ScreenPtr screen = dst->pScreen; PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); int x_off, y_off, i; if (src != dst) { @@ -161,6 +177,15 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &x_off, &y_off); for (i = 0; i < nbox; i++) { + if(glamor_priv->yInverted) { + glRasterPos2i(box[i].x1 + x_off, + box[i].y1 + y_off); + glCopyPixels(box[i].x1 + dx + x_off, + box[i].y1 + dy + y_off, + box[i].x2 - box[i].x1, + box[i].y2 - box[i].y1, + GL_COLOR); + } else { int flip_y1 = dst_pixmap->drawable.height - box[i].y2 + y_off; glRasterPos2i(box[i].x1 + x_off, flip_y1); @@ -169,6 +194,7 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, box[i].x2 - box[i].x1, box[i].y2 - box[i].y1, GL_COLOR); + } } return TRUE; @@ -235,23 +261,39 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glUseProgramObjectARB(glamor_priv->finish_access_prog); for (i = 0; i < nbox; i++) { + vertices[0][0] = v_from_x_coord_x(dst_pixmap, box[i].x1 + dst_x_off); - vertices[0][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); vertices[1][0] = v_from_x_coord_x(dst_pixmap, box[i].x2 + dst_x_off); - vertices[1][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); vertices[2][0] = v_from_x_coord_x(dst_pixmap, box[i].x2 + dst_x_off); - vertices[2][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); vertices[3][0] = v_from_x_coord_x(dst_pixmap, box[i].x1 + dst_x_off); + texcoords[0][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); + texcoords[1][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); + texcoords[2][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); + texcoords[3][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); + + if(glamor_priv->yInverted) { + + vertices[0][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y1 + dst_y_off); + vertices[1][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y1 + dst_y_off); + vertices[2][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y2 + dst_y_off); + vertices[3][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y2 + dst_y_off); + + texcoords[0][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y1 + dy); + texcoords[1][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y1 + dy); + texcoords[2][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y2 + dy); + texcoords[3][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y2 + dy); + } else { + + vertices[0][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); + vertices[1][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); + vertices[2][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); vertices[3][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); - texcoords[0][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); texcoords[0][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); - texcoords[1][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); texcoords[1][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); - texcoords[2][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); texcoords[2][1] = t_from_x_coord_y(src_pixmap, box[i].y2 + dy); - texcoords[3][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); texcoords[3][1] = t_from_x_coord_y(src_pixmap, box[i].y2 + dy); + } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index a4036c89e..3d1d3f842 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -294,12 +294,14 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) unsigned int stride, read_stride, x, y; GLenum format, type; uint8_t *data, *read; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(drawable->pScreen); if (pixmap_priv == NULL) return TRUE; if (pixmap_priv->fb == 0) { - ScreenPtr screen = pixmap->drawable.pScreen; + ScreenPtr screen = pixmap->drawable.pScreen; PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); if (pixmap != screen_pixmap) @@ -343,11 +345,13 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) glPixelStorei(GL_PACK_ROW_LENGTH, read_stride); } if (GLEW_MESA_pack_invert && drawable->depth != 1) { - glPixelStorei(GL_PACK_INVERT_MESA, 1); + if (!glamor_priv->yInverted) + glPixelStorei(GL_PACK_INVERT_MESA, 1); glReadPixels(0, 0, pixmap->drawable.width, pixmap->drawable.height, format, type, data); - glPixelStorei(GL_PACK_INVERT_MESA, 0); + if (!glamor_priv->yInverted) + glPixelStorei(GL_PACK_INVERT_MESA, 0); } else { glGenBuffersARB(1, &pixmap_priv->pbo); glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); @@ -362,10 +366,15 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) if (pixmap->drawable.depth == 1) { for (y = 0; y < pixmap->drawable.height; y++) { - uint8_t *read_row = read + - read_stride * (pixmap->drawable.height - y - 1); + uint8_t *read_row; uint8_t *write_row = data + y * stride; + if (glamor_priv->yInverted) + read_row = read + read_stride * y; + else + read_row = read + + read_stride * (pixmap->drawable.height - y - 1); + for (x = 0; x < pixmap->drawable.width; x++) { int index = x / 8; int bit = 1 << (x % 8); @@ -378,6 +387,9 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) } } else { for (y = 0; y < pixmap->drawable.height; y++) + if (glamor_priv->yInverted) + memcpy(data + y * stride, read + y * stride, stride); + else memcpy(data + y * stride, read + (pixmap->drawable.height - y - 1) * stride, stride); } @@ -452,10 +464,20 @@ glamor_finish_access(DrawablePtr drawable) {1, 1}, {1, 0}, {0, 0}}; + GLuint tex; + static float texcoords_inverted[4][2] = {{0, 0}, + {1, 0}, + {1, 1}, + {0, 1}}; + static float *ptexcoords; if (pixmap_priv == NULL) return; + if (glamor_priv->yInverted) + ptexcoords = texcoords_inverted; + else + ptexcoords = texcoords; if (pixmap_priv->fb == 0) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -496,7 +518,7 @@ glamor_finish_access(DrawablePtr drawable) glEnableClientState(GL_VERTEX_ARRAY); glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, ptexcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index c3e0528bf..1a982054a 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -153,14 +153,21 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glEnableClientState(GL_VERTEX_ARRAY); vertices[0][0] = v_from_x_coord_x(pixmap, x1); - vertices[0][1] = v_from_x_coord_y(pixmap, y1); vertices[1][0] = v_from_x_coord_x(pixmap, x2); - vertices[1][1] = v_from_x_coord_y(pixmap, y1); vertices[2][0] = v_from_x_coord_x(pixmap, x2); - vertices[2][1] = v_from_x_coord_y(pixmap, y2); vertices[3][0] = v_from_x_coord_x(pixmap, x1); - vertices[3][1] = v_from_x_coord_y(pixmap, y2); - + + if (glamor_priv->yInverted) { + vertices[0][1] = v_from_x_coord_y_inverted(pixmap, y1); + vertices[1][1] = v_from_x_coord_y_inverted(pixmap, y1); + vertices[2][1] = v_from_x_coord_y_inverted(pixmap, y2); + vertices[3][1] = v_from_x_coord_y_inverted(pixmap, y2); + } else { + vertices[0][1] = v_from_x_coord_y(pixmap, y1); + vertices[1][1] = v_from_x_coord_y(pixmap, y1); + vertices[2][1] = v_from_x_coord_y(pixmap, y2); + vertices[3][1] = v_from_x_coord_y(pixmap, y2); + } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 9b77f28db..e35c4168a 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -53,6 +53,8 @@ glamor_get_spans(DrawablePtr drawable, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; + 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 x_off, y_off; @@ -85,12 +87,21 @@ glamor_get_spans(DrawablePtr drawable, 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, + (points[i].y + y_off), + widths[i], + 1, + format, type, + readpixels_dst); + } else { glReadPixels(points[i].x + x_off, pixmap->drawable.height - 1 - (points[i].y + y_off), widths[i], 1, format, type, readpixels_dst); + } if (temp_dst) { for (j = 0; j < widths[i]; j++) { set_bit((uint8_t *)dst, j, temp_dst[j] & 0x1); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index c2f516d9c..f12016d33 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -142,7 +142,7 @@ typedef struct glamor_screen_private { BitmapToRegionProcPtr saved_bitmap_to_region; char *delayed_fallback_string; - + int yInverted; GLuint vbo; int vbo_offset; int vbo_size; @@ -268,6 +268,13 @@ v_from_x_coord_y(PixmapPtr pixmap, int y) 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; +} + + static inline float t_from_x_coord_x(PixmapPtr pixmap, int x) { @@ -280,6 +287,13 @@ t_from_x_coord_y(PixmapPtr pixmap, int y) 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; +} + + /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index ead5b692e..6a9c1aa60 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -377,13 +377,9 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, src_y2 = (float)(y2 - y) / h; vertices[0][0] = v_from_x_coord_x(pixmap, x1 + x_off); - vertices[0][1] = v_from_x_coord_y(pixmap, y1 + y_off); vertices[1][0] = v_from_x_coord_x(pixmap, x2 + x_off); - vertices[1][1] = v_from_x_coord_y(pixmap, y1 + y_off); vertices[2][0] = v_from_x_coord_x(pixmap, x2 + x_off); - vertices[2][1] = v_from_x_coord_y(pixmap, y2 + y_off); vertices[3][0] = v_from_x_coord_x(pixmap, x1 + x_off); - vertices[3][1] = v_from_x_coord_y(pixmap, y2 + y_off); texcoords[0][0] = src_x1; texcoords[0][1] = src_y1; @@ -393,7 +389,23 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, texcoords[2][1] = src_y2; texcoords[3][0] = src_x1; texcoords[3][1] = src_y2; + + if (glamor_priv->yInverted) { + + vertices[0][1] = v_from_x_coord_y_inverted(pixmap, y1 + y_off); + vertices[1][1] = v_from_x_coord_y_inverted(pixmap, y1 + y_off); + vertices[2][1] = v_from_x_coord_y_inverted(pixmap, y2 + y_off); + vertices[3][1] = v_from_x_coord_y_inverted(pixmap, y2 + y_off); + + } else { + + vertices[0][1] = v_from_x_coord_y(pixmap, y1 + y_off); + vertices[1][1] = v_from_x_coord_y(pixmap, y1 + y_off); + vertices[2][1] = v_from_x_coord_y(pixmap, y2 + y_off); + vertices[3][1] = v_from_x_coord_y(pixmap, y2 + y_off); + + } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index de57f5219..2ec811f6e 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -556,6 +556,8 @@ glamor_set_transformed_point(PicturePtr picture, PixmapPtr pixmap, 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++) { @@ -570,7 +572,10 @@ glamor_set_transformed_point(PicturePtr picture, PixmapPtr pixmap, ty = y; } texcoord[0] = t_from_x_coord_x(pixmap, tx); - texcoord[1] = t_from_x_coord_y(pixmap, ty); + 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 @@ -887,21 +892,33 @@ glamor_composite_with_shader(CARD8 op, 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[1] = v_from_x_coord_y(dest_pixmap, - box[i].y1 + dest_y_off); vertices[2] = v_from_x_coord_x(dest_pixmap, box[i].x2 + dest_x_off); - vertices[3] = v_from_x_coord_y(dest_pixmap, - box[i].y1 + dest_y_off); vertices[4] = v_from_x_coord_x(dest_pixmap, box[i].x2 + dest_x_off); - vertices[5] = v_from_x_coord_y(dest_pixmap, - box[i].y2 + dest_y_off); vertices[6] = v_from_x_coord_x(dest_pixmap, box[i].x1 + dest_x_off); - vertices[7] = v_from_x_coord_y(dest_pixmap, + + 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; diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 60a1a1e8f..58923701e 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -120,23 +120,36 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glEnable(GL_TEXTURE_2D); vertices[0][0] = v_from_x_coord_x(pixmap, x1); - vertices[0][1] = v_from_x_coord_y(pixmap, y1); vertices[1][0] = v_from_x_coord_x(pixmap, x2); - vertices[1][1] = v_from_x_coord_y(pixmap, y1); vertices[2][0] = v_from_x_coord_x(pixmap, x2); - vertices[2][1] = v_from_x_coord_y(pixmap, y2); vertices[3][0] = v_from_x_coord_x(pixmap, x1); - vertices[3][1] = v_from_x_coord_y(pixmap, y2); - source_texcoords[0][0] = t_from_x_coord_x(tile, tile_x1); - source_texcoords[0][1] = t_from_x_coord_y(tile, tile_y1); source_texcoords[1][0] = t_from_x_coord_x(tile, tile_x2); - source_texcoords[1][1] = t_from_x_coord_y(tile, tile_y1); source_texcoords[2][0] = t_from_x_coord_x(tile, tile_x2); - source_texcoords[2][1] = t_from_x_coord_y(tile, tile_y2); source_texcoords[3][0] = t_from_x_coord_x(tile, tile_x1); - source_texcoords[3][1] = t_from_x_coord_y(tile, tile_y2); + + if (glamor_priv->yInverted) { + vertices[0][1] = v_from_x_coord_y_inverted(pixmap, y1); + vertices[1][1] = v_from_x_coord_y_inverted(pixmap, y1); + vertices[2][1] = v_from_x_coord_y_inverted(pixmap, y2); + vertices[3][1] = v_from_x_coord_y_inverted(pixmap, y2); + source_texcoords[0][1] = t_from_x_coord_y_inverted(tile, tile_y1); + source_texcoords[1][1] = t_from_x_coord_y_inverted(tile, tile_y1); + source_texcoords[2][1] = t_from_x_coord_y_inverted(tile, tile_y2); + source_texcoords[3][1] = t_from_x_coord_y_inverted(tile, tile_y2); + } else { + + vertices[0][1] = v_from_x_coord_y(pixmap, y1); + vertices[1][1] = v_from_x_coord_y(pixmap, y1); + vertices[2][1] = v_from_x_coord_y(pixmap, y2); + vertices[3][1] = v_from_x_coord_y(pixmap, y2); + + source_texcoords[0][1] = t_from_x_coord_y(tile, tile_y1); + source_texcoords[1][1] = t_from_x_coord_y(tile, tile_y1); + source_texcoords[2][1] = t_from_x_coord_y(tile, tile_y2); + source_texcoords[3][1] = t_from_x_coord_y(tile, tile_y2); + } glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); diff --git a/hw/kdrive/ephyr/ephyr_glamor.c b/hw/kdrive/ephyr/ephyr_glamor.c index 70b466388..027cfc52f 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); + glamor_init(screen, 0); return TRUE; } From 18a52e23882e4664fdb2de4958c4f9c97e16068c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 12 May 2011 01:37:52 +0800 Subject: [PATCH 111/462] glamor-ddx: Migrate the code to latest mesa library. Use eglCreateDRMImageMESA to create surfaceless image. And then export the drm buffer back which can be used to create the frame buffer. --- hw/xfree86/glamor/glamor.c | 129 ++++++++++++++++---------------- hw/xfree86/glamor/glamor_crtc.c | 4 +- 2 files changed, 66 insertions(+), 67 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index b80d58758..61db4ad78 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -27,6 +27,9 @@ * */ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif #include #include #include @@ -85,11 +88,11 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) EGLImageKHR image; GLuint texture; EGLint attribs[] = { - EGL_IMAGE_WIDTH_INTEL, 0, - EGL_IMAGE_HEIGHT_INTEL, 0, - EGL_IMAGE_FORMAT_INTEL, EGL_FORMAT_RGBA_8888_KHR, - EGL_IMAGE_USE_INTEL, EGL_IMAGE_USE_SHARE_INTEL | - EGL_IMAGE_USE_SCANOUT_INTEL, + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA | + EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; @@ -99,9 +102,8 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) attribs[1] = width; attribs[3] = height; - image = eglCreateImageKHR(glamor->display, glamor->context, - EGL_SYSTEM_IMAGE_INTEL, - NULL, attribs); + EGLint name, handle, stride, i; + image = eglCreateDRMImageMESA(glamor->display, attribs); if (image == EGL_NO_IMAGE_KHR) return FALSE; @@ -109,14 +111,13 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); glamor_set_pixmap_texture(screen->GetScreenPixmap(screen), width, height, texture); glamor->root = image; scrn->virtualX = width; scrn->virtualY = height; - return TRUE; } @@ -125,49 +126,24 @@ glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) { struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); EGLint name; - - eglShareImageINTEL (glamor->display, glamor->context, glamor->root, 0, - &name, (EGLint *) handle, (EGLint *) pitch); + eglExportDRMImageMESA (glamor->display, glamor->root, &name, (EGLint*) handle, (EGLint*) pitch); } -Bool -glamor_load_cursor(ScrnInfoPtr scrn, CARD32 *image, int width, int height) +EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) { struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + EGLint attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA | + EGL_DRM_BUFFER_USE_SCANOUT_MESA | EGL_DRM_BUFFER_USE_CURSOR_MESA, + EGL_NONE + }; - if (glamor->cursor == NULL) { - EGLint attribs[] = { - EGL_IMAGE_WIDTH_INTEL, 0, - EGL_IMAGE_HEIGHT_INTEL, 0, - EGL_IMAGE_FORMAT_INTEL, EGL_FORMAT_RGBA_8888_KHR, - EGL_IMAGE_USE_INTEL, EGL_IMAGE_USE_SHARE_INTEL | - EGL_IMAGE_USE_SCANOUT_INTEL, - EGL_NONE - }; - - attribs[1] = width; - attribs[3] = height; - glamor->cursor = - eglCreateImageKHR(glamor->display, glamor->context, - EGL_SYSTEM_IMAGE_INTEL, - NULL, attribs); - if (image == EGL_NO_IMAGE_KHR) - return FALSE; - - glGenTextures(1, &glamor->cursor_tex); - glBindTexture(GL_TEXTURE_2D, glamor->cursor_tex); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, glamor->cursor); - } - - glBindTexture(GL_TEXTURE_2D, glamor->cursor_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); - - return TRUE; + attribs[1] = width; + attribs[3] = height; + return eglCreateDRMImageMESA(glamor->display, attribs); } void @@ -175,9 +151,7 @@ glamor_cursor_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) { struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); EGLint name; - - eglShareImageINTEL (glamor->display, glamor->context, glamor->cursor, - 0, &name, (EGLint *) handle, (EGLint *) pitch); + eglExportDRMImageMESA (glamor->display, glamor->cursor, &name, (EGLint*) handle, (EGLint*) pitch); ErrorF("cursor stride: %d\n", *pitch); } @@ -190,8 +164,7 @@ glamor_pre_init(ScrnInfoPtr scrn, int flags) glamor = xnfcalloc(sizeof *glamor, 1); scrn->driverPrivate = glamor; - - glamor->fd = open("/dev/dri/card0", O_RDWR); + glamor->fd = open("/dev/dri/card1", O_RDWR); glamor->cpp = 4; scrn->monitor = scrn->confScreen->monitor; @@ -243,7 +216,10 @@ glamor_enter_vt(int scrnIndex, int flags) "drmSetMaster failed: %s\n", strerror(errno)); return FALSE; } - +#if 0 + if (!xf86SetDesiredModes(scrn)) + return FALSE; +#endif return TRUE; } @@ -266,6 +242,7 @@ glamor_create_screen_resources(ScreenPtr screen) if (!(*screen->CreateScreenResources) (screen)) return FALSE; + if (!xf86SetDesiredModes(scrn)) return FALSE; @@ -300,15 +277,12 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); - EGLDisplayTypeDRMMESA display; const char *version; + VisualPtr visual; - display.type = EGL_DISPLAY_TYPE_DRM_MESA; - display.device = NULL; - display.fd = glamor->fd; - - glamor->display = eglGetDisplay((EGLNativeDisplayType) &display); - + glamor->display = eglGetDRMDisplayMESA(glamor->fd); + eglBindAPI(EGL_OPENGL_API); + LogMessageVerb(X_INFO, 0, "%s glCreateProgramObjectARB=%p", __FUNCTION__, *(&glCreateProgramObjectARB)); if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); @@ -325,6 +299,7 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) "Failed to create EGL context\n"); return FALSE; } + if (!eglMakeCurrent(glamor->display, EGL_NO_SURFACE, EGL_NO_SURFACE, glamor->context)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, @@ -346,16 +321,29 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) 1, scrn->bitsPerPixel)) return FALSE; - fbPictureInit(screen, NULL, 0); + if (scrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = screen->visuals + screen->numVisuals; + while(--visual >= screen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = scrn->offset.red; + visual->offsetGreen = scrn->offset.green; + visual->offsetBlue = scrn->offset.blue; + visual->redMask = scrn->mask.red; + visual->blueMask = scrn->mask.blue; + } + } + } + fbPictureInit(screen, NULL, 0); xf86SetBlackWhitePixels(screen); - if (!glamor_init(screen)) { + if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to initialize glamor\n"); return FALSE; } - + miInitializeBackingStore(screen); xf86SetBackingStore(screen); xf86SetSilkenMouse(screen); @@ -369,7 +357,7 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) HARDWARE_CURSOR_INVERT_MASK | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | + HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED | HARDWARE_CURSOR_UPDATE_UNHIDDEN | HARDWARE_CURSOR_ARGB))) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, @@ -389,6 +377,15 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) glamor->CloseScreen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; + /* Fixme should we init crtc screen here? */ + if (!xf86CrtcScreenInit(screen)) + return FALSE; + if (!miCreateDefColormap(screen)) + return FALSE; + /* Fixme should we add handle colormap here? */ + + xf86DPMSInit(screen, xf86DPMSSet, 0); + return TRUE; } @@ -423,6 +420,8 @@ glamor_probe(struct _DriverRec *drv, int flags) ScrnInfoPtr scrn = NULL; GDevPtr *sections; int entity, n; + LogMessageVerb(X_INFO, 0 , "%s : %d \n", __FUNCTION__, __LINE__); + n = xf86MatchDevice(glamor_name, §ions); if (n <= 0) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 4c9181922..352f79f79 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -328,7 +328,7 @@ drmmode_update_fb (ScrnInfoPtr scrn, int width, int height) drmModeRmFB(drmmode->fd, drmmode->fb_id); glamor_frontbuffer_handle(scrn, &handle, &pitch); ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, - scrn->bitsPerPixel, pitch * drmmode->cpp, + scrn->bitsPerPixel, pitch, handle, &drmmode->fb_id); if (ret) /* FIXME: Undo glamor_resize() */ @@ -461,7 +461,7 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { ScrnInfoPtr scrn = crtc->scrn; - glamor_load_cursor(scrn, image, 64, 64); + //glamor_load_cursor(scrn, image, 64, 64); } From 43280372686177603111b175e92e1c88ad4ccdee Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 12 May 2011 01:42:05 +0800 Subject: [PATCH 112/462] glamor-ddx: Fix a compiling error. Need revisit. GC is redefined in the X11/Xlib.h and include/gcstruct.h which is a xorg header file. Just use a macro to simply avoid the conflict. Need revisit latter to find a correct way to fix this problem. --- hw/xfree86/glamor/glamor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 61db4ad78..59475288f 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -45,7 +45,9 @@ #include "../../../mi/micmap.h" #include #include +#define GC XORG_GC #include +#undef GC #include "glamor_ddx.h" From e3295d4106ac5b62f63e32dcb24a6094194cb1a8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 12 May 2011 10:22:07 +0800 Subject: [PATCH 113/462] glamor-ddx: Move the cursor EGL image to crtc strcture. Cursor is a per crtc resource. And this commit also fix the cursor initialization regard to the latest mesa EGL code. Now hardware cursor works fine. --- hw/xfree86/glamor/glamor.c | 42 ++++++++++++++++++++------------- hw/xfree86/glamor/glamor_crtc.c | 41 ++++++++++++++++++++++++++++---- hw/xfree86/glamor/glamor_ddx.h | 4 ++-- 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 59475288f..bf05a0b2f 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -66,9 +66,8 @@ glamor_identify(int flags) struct glamor_screen_private { EGLDisplay display; EGLContext context; - EGLImageKHR root, cursor; + EGLImageKHR root; EGLint major, minor; - GLuint cursor_tex; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; @@ -149,14 +148,15 @@ EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) } void -glamor_cursor_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) +glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uint32_t *pitch) { struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); EGLint name; - eglExportDRMImageMESA (glamor->display, glamor->cursor, &name, (EGLint*) handle, (EGLint*) pitch); + eglExportDRMImageMESA (glamor->display, cursor, &name, (EGLint*) handle, (EGLint*) pitch); ErrorF("cursor stride: %d\n", *pitch); } +char * dri_device_name = "/dev/dri/card0"; static Bool glamor_pre_init(ScrnInfoPtr scrn, int flags) { @@ -166,7 +166,12 @@ glamor_pre_init(ScrnInfoPtr scrn, int flags) glamor = xnfcalloc(sizeof *glamor, 1); scrn->driverPrivate = glamor; - glamor->fd = open("/dev/dri/card1", O_RDWR); + glamor->fd = open(dri_device_name, O_RDWR); + if (glamor->fd == -1 ) { + ErrorF("Failed to open %s: %s\n", dri_device_name, strerror(errno)); + goto fail; + } + glamor->cpp = 4; scrn->monitor = scrn->confScreen->monitor; @@ -174,22 +179,21 @@ glamor_pre_init(ScrnInfoPtr scrn, int flags) scrn->rgbBits = 8; if (!xf86SetDepthBpp(scrn, 0, 0, 0, Support32bppFb)) - return FALSE; + goto fail; xf86PrintDepthBpp(scrn); if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) - return FALSE; + goto fail; if (!xf86SetDefaultVisual(scrn, -1)) - return FALSE; + goto fail; glamor->cpp = scrn->bitsPerPixel / 8; if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); - xfree(glamor); - return FALSE; + goto fail; } scrn->currentMode = scrn->modes; @@ -197,9 +201,13 @@ glamor_pre_init(ScrnInfoPtr scrn, int flags) /* Load the required sub modules */ if (!xf86LoadSubModule(scrn, "fb")) - return FALSE; + goto fail; return TRUE; + +fail: + scrn->driverPrivate = NULL; + xfree(glamor); } static void @@ -396,10 +404,12 @@ glamor_free_screen(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); - - close(glamor->fd); - xfree(scrn->driverPrivate); - scrn->driverPrivate = NULL; + if (glamor != NULL) + { + close(glamor->fd); + xfree(glamor); + scrn->driverPrivate = NULL; + } } static ModeStatus @@ -422,8 +432,6 @@ glamor_probe(struct _DriverRec *drv, int flags) ScrnInfoPtr scrn = NULL; GDevPtr *sections; int entity, n; - LogMessageVerb(X_INFO, 0 , "%s : %d \n", __FUNCTION__, __LINE__); - n = xf86MatchDevice(glamor_name, §ions); if (n <= 0) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 352f79f79..9425b6970 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -48,6 +48,14 @@ #include #include #include +#include + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#define EGL_DISPLAY_NO_X_MESA +#include +#include +#include #include "glamor_ddx.h" @@ -67,6 +75,7 @@ typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; uint32_t rotate_fb_id; + EGLImageKHR cursor; unsigned int cursor_tex; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; @@ -328,7 +337,7 @@ drmmode_update_fb (ScrnInfoPtr scrn, int width, int height) drmModeRmFB(drmmode->fd, drmmode->fb_id); glamor_frontbuffer_handle(scrn, &handle, &pitch); ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, - scrn->bitsPerPixel, pitch, + scrn->bitsPerPixel, pitch /** drmmode->cpp*/, handle, &drmmode->fb_id); if (ret) /* FIXME: Undo glamor_resize() */ @@ -459,9 +468,31 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) static void drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; ScrnInfoPtr scrn = crtc->scrn; - //glamor_load_cursor(scrn, image, 64, 64); + + if (drmmode_crtc->cursor == NULL) + { + drmmode_crtc->cursor = glamor_create_cursor_argb(scrn, 64, 64); + if (drmmode_crtc->cursor == EGL_NO_IMAGE_KHR) + return; + glGenTextures(1, &drmmode_crtc->cursor_tex); + glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, drmmode_crtc->cursor); + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); + glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); + // memset(image, 0xff, 64*64*4); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image); + } @@ -484,7 +515,7 @@ drmmode_show_cursor (xf86CrtcPtr crtc) uint32_t handle, stride; ErrorF("show cursor\n"); - glamor_cursor_handle(scrn, &handle, &stride); + glamor_cursor_handle(scrn, drmmode_crtc->cursor, &handle, &stride); drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64); @@ -596,6 +627,7 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .show_cursor = drmmode_show_cursor, .hide_cursor = drmmode_hide_cursor, .load_cursor_argb = drmmode_load_cursor_argb, + .load_cursor_image = NULL, #if 0 .shadow_create = drmmode_crtc_shadow_create, .shadow_allocate = drmmode_crtc_shadow_allocate, @@ -1311,9 +1343,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) if (!crtc->enabled) continue; - +#if 0 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); +#endif } return TRUE; diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index 0968f013f..0f7cbe47e 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -6,8 +6,8 @@ void glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch); Bool glamor_load_cursor(ScrnInfoPtr scrn, CARD32 *image, int width, int height); -void glamor_cursor_handle(ScrnInfoPtr scrn, - uint32_t *handle, uint32_t *pitch); + +void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR image, uint32_t *handle, uint32_t *pitch); Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); void drmmode_closefb(ScrnInfoPtr scrn); From c97d4533f29e77d80c076deff9ad0f218eb2e8f4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 12 May 2011 14:49:08 +0800 Subject: [PATCH 114/462] glamor: Silent compilation warnings due to some deprecated APIs. those xcalloc/xfree/xalloc/XNFprintf/... are deprecated. Replace then with the new one. And fix some other minor problems. --- glamor/glamor.c | 15 +++++++-------- glamor/glamor_core.c | 10 +++++----- glamor/glamor_getspans.c | 4 ++-- glamor/glamor_glyphs.c | 8 ++++---- glamor/glamor_polylines.c | 6 +++--- glamor/glamor_priv.h | 4 ++-- glamor/glamor_render.c | 27 +++++++++++++++------------ glamor/glamor_setspans.c | 4 ++-- glamor/glu3/glu3.h | 31 ------------------------------- hw/xfree86/glamor/glamor.c | 8 ++++---- hw/xfree86/glamor/glamor_crtc.c | 25 +++++++++++-------------- hw/xfree86/glamor/glamor_ddx.h | 1 + 12 files changed, 56 insertions(+), 87 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 026f1bf52..66a694ec9 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -102,7 +102,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); - if (dixAllocatePrivates(pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { + if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { fbDestroyPixmap(pixmap); ErrorF("Fail to allocate privates for PIXMAP.\n"); return NullPixmap; @@ -166,16 +166,15 @@ glamor_init(ScreenPtr screen, unsigned int flags) { glamor_screen_private *glamor_priv; - if (flags & ~GLAMOR_VALID_FLAGS) { - ErrorF("glamor_init: Invalid flags %x\n", flags); - return FALSE; - } - #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif - glamor_priv = xcalloc(1, sizeof(*glamor_priv)); + if (flags & ~GLAMOR_VALID_FLAGS) { + ErrorF("glamor_init: Invalid flags %x\n", flags); + return FALSE; + } + glamor_priv = calloc(1, sizeof(*glamor_priv)); if (glamor_priv == NULL) return FALSE; @@ -274,7 +273,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) return TRUE; fail: - xfree(glamor_priv); + free(glamor_priv); dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL); return FALSE; } diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 3d1d3f842..09605e222 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -311,7 +311,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) stride = pixmap->devKind; read_stride = stride; - data = xalloc(stride * pixmap->drawable.height); + data = malloc(stride * pixmap->drawable.height); switch (drawable->depth) { case 1: @@ -332,7 +332,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) break; default: ErrorF("Unknown prepareaccess depth %d\n", drawable->depth); - xfree(data); + free(data); return FALSE; } @@ -475,9 +475,9 @@ glamor_finish_access(DrawablePtr drawable) if (pixmap_priv == NULL) return; if (glamor_priv->yInverted) - ptexcoords = texcoords_inverted; + ptexcoords = &texcoords_inverted[0][0]; else - ptexcoords = texcoords; + ptexcoords = &texcoords[0][0]; if (pixmap_priv->fb == 0) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -549,7 +549,7 @@ glamor_finish_access(DrawablePtr drawable) glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); - xfree(pixmap->devPrivate.ptr); + free(pixmap->devPrivate.ptr); pixmap->devPrivate.ptr = NULL; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index e35c4168a..dba23a89d 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -61,7 +61,7 @@ glamor_get_spans(DrawablePtr drawable, switch (drawable->depth) { case 1: - temp_dst = xalloc(wmax); + temp_dst = malloc(wmax); format = GL_ALPHA; type = GL_UNSIGNED_BYTE; readpixels_dst = temp_dst; @@ -111,7 +111,7 @@ glamor_get_spans(DrawablePtr drawable, readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } } - xfree(temp_dst); + free(temp_dst); return; fail: diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 6e5595e68..e24b222f4 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -130,12 +130,12 @@ static void glamor_unrealize_glyph_caches(ScreenPtr screen, unsigned int format) } if (cache->hash_entries) { - xfree(cache->hash_entries); + free(cache->hash_entries); cache->hash_entries = NULL; } if (cache->glyphs) { - xfree(cache->glyphs); + free(cache->glyphs); cache->glyphs = NULL; } cache->glyph_count = 0; @@ -215,9 +215,9 @@ static Bool glamor_realize_glyph_caches(ScreenPtr screen, unsigned int format) cache->picture = picture; cache->picture->refcnt++; - cache->hash_entries = xalloc(sizeof(int) * cache->hash_size); + cache->hash_entries = malloc(sizeof(int) * cache->hash_size); cache->glyphs = - xalloc(sizeof(glamor_cached_glyph_t) * cache->size); + malloc(sizeof(glamor_cached_glyph_t) * cache->size); cache->glyph_count = 0; if (!cache->hash_entries || !cache->glyphs) diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index acf6bf673..c9752685f 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -64,7 +64,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, goto fail; } - rects = xalloc(sizeof(xRectangle) * (n - 1)); + rects = malloc(sizeof(xRectangle) * (n - 1)); x1 = points[0].x; y1 = points[0].y; /* If we have any non-horizontal/vertical, fall back. */ @@ -80,7 +80,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, if (x1 != x2 && y1 != y2) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - xfree(rects); + free(rects); ErrorF("stub diagonal poly_line\n"); glamor_solid_fail_region(pixmap, x1, y1, x2 - x1, y2 - y1); @@ -106,7 +106,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, y1 = y2; } gc->ops->PolyFillRect(drawable, gc, n - 1, rects); - xfree(rects); + free(rects); return; fail: diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index f12016d33..b98907837 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -231,7 +231,7 @@ glamor_delayed_fallback(ScreenPtr screen, char *format, ...) return; va_start(ap, format); - glamor_priv->delayed_fallback_string = XNFvprintf(format, ap); + XNFvasprintf(&glamor_priv->delayed_fallback_string, format, ap); va_end(ap); } @@ -240,7 +240,7 @@ glamor_clear_delayed_fallbacks(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - xfree(glamor_priv->delayed_fallback_string); + free(glamor_priv->delayed_fallback_string); glamor_priv->delayed_fallback_string = NULL; } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 2ec811f6e..6139b0d02 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -181,13 +181,15 @@ glamor_create_composite_fs(struct shader_key *key) FatalError("Bad composite IN type"); } - source = XNFprintf("%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); - xfree(source); + free(source); return prog; } @@ -216,14 +218,15 @@ glamor_create_composite_vs(struct shader_key *key) if (key->mask != SHADER_MASK_NONE && key->mask != SHADER_MASK_SOLID) mask_coords_setup = mask_coords; - source = XNFprintf("%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); - xfree(source); + free(source); return prog; } @@ -591,7 +594,7 @@ glamor_setup_composite_vbo(ScreenPtr screen) glBindBufferARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo); glVertexPointer(2, GL_FLOAT, glamor_priv->vb_stride, - (void *)(glamor_priv->vbo_offset)); + (void *)((long)glamor_priv->vbo_offset)); glEnableClientState(GL_VERTEX_ARRAY); if (glamor_priv->has_source_coords) { diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 54aa26635..6c1c2ff3f 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -53,7 +53,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, switch (drawable->depth) { case 1: - temp_src = xalloc(wmax); + temp_src = malloc(wmax); format = GL_ALPHA; type = GL_UNSIGNED_BYTE; drawpixels_src = temp_src; @@ -123,7 +123,7 @@ fail: glDisable(GL_SCISSOR_TEST); glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(GXcopy); - xfree(temp_src); + free(temp_src); glamor_fallback("glamor_set_spans(): to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); diff --git a/glamor/glu3/glu3.h b/glamor/glu3/glu3.h index 27bcebc80..0a698cc02 100644 --- a/glamor/glu3/glu3.h +++ b/glamor/glu3/glu3.h @@ -123,44 +123,14 @@ typedef struct GLUmat4Stack GLUmat4Stack; #ifdef __cplusplus extern "C" { #endif -#if 0 -GLfloat gluDot4_4v(const GLUvec4 *, const GLUvec4 *); -GLfloat gluDot3_4v(const GLUvec4 *, const GLUvec4 *); -GLfloat gluDot2_4v(const GLUvec4 *, const GLUvec4 *); - -void gluCross4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); -void gluNormalize4v(GLUvec4 *result, const GLUvec4 *); -GLfloat gluLength4v(const GLUvec4 *); -GLfloat gluLengthSqr4v(const GLUvec4 *); -void gluOuter4v(GLUmat4 *result, const GLUvec4 *, const GLUvec4 *); - - -void gluMult4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); -void gluDiv4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); -void gluAdd4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); -void gluSub4v_4v(GLUvec4 *result, const GLUvec4 *, const GLUvec4 *); - -void gluMult4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); -void gluDiv4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); -void gluAdd4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); -void gluSub4v_f(GLUvec4 *result, const GLUvec4 *, GLfloat); - -void gluMult4m_4m(GLUmat4 *result, const GLUmat4 *, const GLUmat4 *); -void gluAdd4m_4m(GLUmat4 *result, const GLUmat4 *, const GLUmat4 *); -void gluSub4m_4m(GLUmat4 *result, const GLUmat4 *, const GLUmat4 *); -void gluMult4m_4v(GLUvec4 *result, const GLUmat4 *m, const GLUvec4 *v); - -void gluMult4m_f(GLUmat4 *result, const GLUmat4 *, GLfloat); void gluScale4v(GLUmat4 *result, const GLUvec4 *); -void gluTranslate3f(GLUmat4 *result, GLfloat x, GLfloat y, GLfloat z); void gluTranslate4v(GLUmat4 *result, const GLUvec4 *); void gluRotate4v(GLUmat4 *result, const GLUvec4 *axis, GLfloat angle); void gluLookAt4v(GLUmat4 *result, const GLUvec4 *eye, const GLUvec4 *center, const GLUvec4 *up); void gluPerspective4f(GLUmat4 *result, GLfloat fovy, GLfloat aspect, GLfloat near, GLfloat far); -void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m); void gluFrustum6f(GLUmat4 *result, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, @@ -169,7 +139,6 @@ void gluOrtho6f(GLUmat4 *result, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far); -#endif extern const GLUmat4 gluIdentityMatrix; #ifdef __cplusplus diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index bf05a0b2f..255661d62 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -103,7 +103,6 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) attribs[1] = width; attribs[3] = height; - EGLint name, handle, stride, i; image = eglCreateDRMImageMESA(glamor->display, attribs); if (image == EGL_NO_IMAGE_KHR) return FALSE; @@ -206,8 +205,9 @@ glamor_pre_init(ScrnInfoPtr scrn, int flags) return TRUE; fail: - scrn->driverPrivate = NULL; - xfree(glamor); + scrn->driverPrivate = NULL; + free(glamor); + return FALSE; } static void @@ -407,7 +407,7 @@ glamor_free_screen(int scrnIndex, int flags) if (glamor != NULL) { close(glamor->fd); - xfree(glamor); + free(glamor); scrn->driverPrivate = NULL; } } diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 9425b6970..fd4ee8671 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -377,7 +377,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, crtc->y = y; crtc->rotation = rotation; - output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output); + output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); if (!output_ids) { ret = FALSE; goto done; @@ -469,10 +469,8 @@ static void drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; ScrnInfoPtr scrn = crtc->scrn; - if (drmmode_crtc->cursor == NULL) { drmmode_crtc->cursor = glamor_create_cursor_argb(scrn, 64, 64); @@ -489,7 +487,6 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); - // memset(image, 0xff, 64*64*4); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image); @@ -775,7 +772,7 @@ static int drmmode_output_lvds_edid(xf86OutputPtr output, * device. This is similar to what we have done in i830_lvds.c */ edid_mon = NULL; - edid_mon = xcalloc(1, sizeof(xf86Monitor)); + edid_mon = calloc(1, sizeof(xf86Monitor)); if (!edid_mon) { xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "Can't allocate memory for edid_mon.\n"); @@ -915,17 +912,17 @@ drmmode_output_destroy(xf86OutputPtr output) drmModeFreePropertyBlob(drmmode_output->edid_blob); for (i = 0; i < drmmode_output->num_props; i++) { drmModeFreeProperty(drmmode_output->props[i].mode_prop); - xfree(drmmode_output->props[i].atoms); + free(drmmode_output->props[i].atoms); } - xfree(drmmode_output->props); + free(drmmode_output->props); drmModeFreeConnector(drmmode_output->mode_output); if (drmmode_output->private_data) { - xfree(drmmode_output->private_data); + free(drmmode_output->private_data); drmmode_output->private_data = NULL; } if (drmmode_output->backlight_iface) drmmode_backlight_set(output, drmmode_output->backlight_active_level); - xfree(drmmode_output); + free(drmmode_output); output->driver_private = NULL; } @@ -1008,7 +1005,7 @@ drmmode_output_create_resources(xf86OutputPtr output) drmModePropertyPtr drmmode_prop; int i, j, err; - drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec)); + drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec)); if (!drmmode_output->props) return; @@ -1033,7 +1030,7 @@ drmmode_output_create_resources(xf86OutputPtr output) INT32 range[2]; p->num_atoms = 1; - p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); + p->atoms = calloc(p->num_atoms, sizeof(Atom)); if (!p->atoms) continue; p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); @@ -1055,7 +1052,7 @@ drmmode_output_create_resources(xf86OutputPtr output) } } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { p->num_atoms = drmmode_prop->count_enums + 1; - p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); + p->atoms = calloc(p->num_atoms, sizeof(Atom)); if (!p->atoms) continue; p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); @@ -1291,7 +1288,7 @@ drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) return; } - drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1); + drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); if (!drmmode_output) { xf86OutputDestroy(output); drmModeFreeConnector(koutput); @@ -1305,7 +1302,7 @@ drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) */ drmmode_output->private_data = NULL; if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) { - drmmode_output->private_data = xcalloc( + drmmode_output->private_data = calloc( sizeof(struct fixed_panel_lvds), 1); if (!drmmode_output->private_data) xf86DrvMsg(scrn->scrnIndex, X_ERROR, diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index 0f7cbe47e..6f8de11ac 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -8,6 +8,7 @@ Bool glamor_load_cursor(ScrnInfoPtr scrn, CARD32 *image, int width, int height); void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR image, uint32_t *handle, uint32_t *pitch); +EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height); Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); void drmmode_closefb(ScrnInfoPtr scrn); From 74ca45e7d0ed6654204189793261ef65f213bb2e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 18 May 2011 16:48:06 +0800 Subject: [PATCH 115/462] glamor-ddx: Fixed one bug when a client reset the connection. This commit fixed two bugs when one client reset the connection. The first is that we should reopen the graphic device when the previous node was closed during the screen closing. The second one is we should call glamor_close_screen (not the ddx version) prior to call eglTerminate(). As eglTerminate will release the share library. And the glamor_close_screen may still need to call openGL APIs and thus will hit segfault. And renamed the ddx functions to avoid naming conflications with the glamor functions. --- hw/xfree86/glamor/glamor.c | 61 +++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 255661d62..665cd0aea 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -157,7 +157,7 @@ glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uin char * dri_device_name = "/dev/dri/card0"; static Bool -glamor_pre_init(ScrnInfoPtr scrn, int flags) +glamor_pre_init_ddx(ScrnInfoPtr scrn, int flags) { struct glamor_screen_private *glamor; rgb defaultWeight = { 0, 0, 0 }; @@ -211,12 +211,12 @@ fail: } static void -glamor_adjust_frame(int scrnIndex, int x, int y, int flags) +glamor_adjust_frame_ddx(int scrnIndex, int x, int y, int flags) { } static Bool -glamor_enter_vt(int scrnIndex, int flags) +glamor_enter_vt_ddx(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); @@ -234,7 +234,7 @@ glamor_enter_vt(int scrnIndex, int flags) } static void -glamor_leave_vt(int scrnIndex, int flags) +glamor_leave_vt_ddx(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); @@ -243,7 +243,7 @@ glamor_leave_vt(int scrnIndex, int flags) } static Bool -glamor_create_screen_resources(ScreenPtr screen) +glamor_create_screen_resources_ddx(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); @@ -260,13 +260,16 @@ glamor_create_screen_resources(ScreenPtr screen) } static Bool -glamor_close_screen(int scrnIndex, ScreenPtr screen) +glamor_close_screen_ddx(int scrnIndex, ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + screen->CloseScreen = glamor->CloseScreen; + (*screen->CloseScreen) (scrnIndex, screen); + if (scrn->vtSema == TRUE) - glamor_leave_vt(scrnIndex, 0); + glamor_leave_vt_ddx(scrnIndex, 0); glamor_fini(screen); @@ -275,21 +278,32 @@ glamor_close_screen(int scrnIndex, ScreenPtr screen) eglTerminate(glamor->display); drmmode_closefb(scrn); - - screen->CloseScreen = glamor->CloseScreen; - (*screen->CloseScreen) (scrnIndex, screen); + + glamor->fd = -1; + glamor->root = EGL_NO_IMAGE_KHR; return TRUE; } static Bool -glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) +glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); const char *version; VisualPtr visual; + /* If serverGeneration != 1 then fd was closed during the last + time closing screen, actually in eglTerminate(). */ + + if (glamor->fd == -1 && serverGeneration != 1) { + glamor->fd = open(dri_device_name, O_RDWR); + if (glamor->fd == -1 ) { + ErrorF("Failed to open %s: %s\n", dri_device_name, strerror(errno)); + return FALSE; + } + } + glamor->display = eglGetDRMDisplayMESA(glamor->fd); eglBindAPI(EGL_OPENGL_API); LogMessageVerb(X_INFO, 0, "%s glCreateProgramObjectARB=%p", __FUNCTION__, *(&glCreateProgramObjectARB)); @@ -378,15 +392,14 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) * later memory should be bound when allocating, e.g rotate_mem */ scrn->vtSema = TRUE; - if (!glamor_enter_vt(scrnIndex, 0)) + if (!glamor_enter_vt_ddx(scrnIndex, 0)) return FALSE; screen->SaveScreen = xf86SaveScreen; glamor->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = glamor_create_screen_resources; + screen->CreateScreenResources = glamor_create_screen_resources_ddx; glamor->CloseScreen = screen->CloseScreen; - screen->CloseScreen = glamor_close_screen; - + screen->CloseScreen = glamor_close_screen_ddx; /* Fixme should we init crtc screen here? */ if (!xf86CrtcScreenInit(screen)) return FALSE; @@ -400,7 +413,7 @@ glamor_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) } static void -glamor_free_screen(int scrnIndex, int flags) +glamor_free_screen_ddx(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); @@ -413,7 +426,7 @@ glamor_free_screen(int scrnIndex, int flags) } static ModeStatus -glamor_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +glamor_valid_mode_ddx(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { if (mode->Flags & V_INTERLACE) { if (verbose) { @@ -450,13 +463,13 @@ glamor_probe(struct _DriverRec *drv, int flags) scrn->name = (char *) glamor_name; scrn->Probe = NULL; - scrn->PreInit = glamor_pre_init; - scrn->ScreenInit = glamor_screen_init; - scrn->AdjustFrame = glamor_adjust_frame; - scrn->EnterVT = glamor_enter_vt; - scrn->LeaveVT = glamor_leave_vt; - scrn->FreeScreen = glamor_free_screen; - scrn->ValidMode = glamor_valid_mode; + scrn->PreInit = glamor_pre_init_ddx; + scrn->ScreenInit = glamor_screen_init_ddx; + scrn->AdjustFrame = glamor_adjust_frame_ddx; + scrn->EnterVT = glamor_enter_vt_ddx; + scrn->LeaveVT = glamor_leave_vt_ddx; + scrn->FreeScreen = glamor_free_screen_ddx; + scrn->ValidMode = glamor_valid_mode_ddx; return TRUE; } From f871d174a861e7c3d2b8f4d9a3f10c38a5120606 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 19 May 2011 11:40:38 +0800 Subject: [PATCH 116/462] glamor: Switch to software fb for too large pixmap. If pixmap's size exceeds the limitation of the MESA library, the rendering will fail. So we switch to software fb if it is the case. Add one new element for pixmap private structure to indicate whehter we are a software fb type or a opengl type. --- glamor/glamor.c | 26 +++++++++++++++++++------- glamor/glamor_priv.h | 18 ++++++++++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 66a694ec9..4594f145c 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -95,12 +95,24 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, PixmapPtr pixmap; GLenum format; GLuint tex; - + glamor_pixmap_private *pixmap_priv; + int type = GLAMOR_GL; if (w > 32767 || h > 32767) return NullPixmap; - pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); + if (w > MAX_WIDTH || h > MAX_HEIGHT) { + /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. + If we exceed such limitation, we have to use framebuffer.*/ + type = GLAMOR_FB; + pixmap = fbCreatePixmap (screen, w, h, depth, usage); + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + (((w * pixmap->drawable.bitsPerPixel + + 7) / 8) + 3) & ~3, + NULL); + ErrorF("fallback to software fb for pixmap %p , %d x %d \n", pixmap, w, h); + } else + pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { fbDestroyPixmap(pixmap); @@ -108,8 +120,12 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; } - if (w == 0 || h == 0) + if (w == 0 || h == 0 || type != GLAMOR_GL) return pixmap; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv->type = type; + /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. * FBOs, which EXT_fbo forgot to do. */ @@ -122,7 +138,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, break; } - /* Create the texture used to store the pixmap's data. */ glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); @@ -132,7 +147,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, format, GL_UNSIGNED_BYTE, NULL); glamor_set_pixmap_texture(pixmap, w, h, tex); - return pixmap; } @@ -141,7 +155,6 @@ 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); } @@ -285,7 +298,6 @@ glamor_close_screen(int idx, ScreenPtr screen) #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif - glamor_glyphs_fini(screen); screen->CloseScreen = glamor_priv->saved_close_screen; screen->CreateGC = glamor_priv->saved_create_gc; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b98907837..93837e0b7 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -39,6 +39,14 @@ #include "glyphstr.h" #endif +#ifndef MAX_WIDTH +#define MAX_WIDTH 4096 +#endif + +#ifndef MAX_HEIGHT +#define MAX_HEIGHT 4096 +#endif + typedef enum glamor_access { GLAMOR_ACCESS_RO, GLAMOR_ACCESS_RW, @@ -175,10 +183,16 @@ typedef struct glamor_screen_private { glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; } glamor_screen_private; +enum glamor_pixmap_type { + GLAMOR_GL, + GLAMOR_FB +}; + typedef struct glamor_pixmap_private { GLuint tex; GLuint fb; GLuint pbo; + enum glamor_pixmap_type type; } glamor_pixmap_private; extern DevPrivateKey glamor_screen_private_key; @@ -250,8 +264,8 @@ 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, 0, "fallback: %s", - glamor_priv->delayed_fallback_string); + // LogMessageVerb(X_INFO, 0, "fallback: %s", + // glamor_priv->delayed_fallback_string); glamor_clear_delayed_fallbacks(screen); } } From 8593f22fb8fc5e0d0f406d9c94cca22347505fd6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 19 May 2011 17:59:19 +0800 Subject: [PATCH 117/462] glamor: glamor_set_alu should enable GL_COLOR_LOGIC_OP. GL_COLOR_OP seems not supported in current MESA. --- glamor/glamor_core.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 09605e222..5f13b56d2 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -117,12 +117,10 @@ void glamor_set_alu(unsigned char alu) { if (alu == GXcopy) { - glDisable(GL_LOGIC_OP); + glDisable(GL_COLOR_LOGIC_OP); return; } - - glEnable(GL_LOGIC_OP); - + glEnable(GL_COLOR_LOGIC_OP); switch (alu) { case GXclear: glLogicOp(GL_CLEAR); @@ -271,10 +269,10 @@ glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, break; case 24: case 32: - color[0] = ubyte_to_float(fg_pixel >> 16); - color[1] = ubyte_to_float(fg_pixel >> 8); - color[2] = ubyte_to_float(fg_pixel >> 0); - color[3] = ubyte_to_float(fg_pixel >> 24); + 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); From cd43b1ea831eac11bc6ad0c3b1e040bb968b9861 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 19 May 2011 18:02:19 +0800 Subject: [PATCH 118/462] glamor: Add fallback code path for glamor_fill. --- glamor/glamor_fill.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 1a982054a..8ea70d0cf 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -84,6 +84,20 @@ glamor_fill(DrawablePtr drawable, drawable->y + y - gc->patOrg.y); break; } + return; +#if 0 + 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); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); + } +#endif +return; + } void @@ -142,8 +156,10 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, if (!glamor_set_destination_pixmap(pixmap)) return; glamor_set_alu(alu); - if (!glamor_set_planemask(pixmap, planemask)) + if (!glamor_set_planemask(pixmap, planemask)) { + ErrorF("Failedto set planemask in glamor_solid.\n"); goto fail; + } glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); From 529c38a4601e8f0712773bf29a48cddfa7a5edc4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 19 May 2011 18:03:12 +0800 Subject: [PATCH 119/462] glamor-ddx: Remove debug message when moving cursor. --- hw/xfree86/glamor/glamor_crtc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index fd4ee8671..aba9b2c29 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -460,8 +460,6 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; - ErrorF("move cursor\n"); - drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); } From 1495ba9e64633476508febb01ec2e9594a7b466b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 22 May 2011 17:51:27 +0800 Subject: [PATCH 120/462] glamor: Use buffer object as much as possible. Change the row length of 1bit color depth pixmap to the actual stride. The previous implementation use the width as its stride which is not good. As it will waste 8 times of space and also bring some non-unify code path. With this commit, we can merge those 1bit or other color depth to almost one code path. And we will use pixel buffer object as much as possible due to performance issue. By default, some mesa hardware driver will fallback to software rasterization when use glReadPixels on a non-buffer-object frame buffer. This change will get about 4x times performance improvemention when we use y-inverted glamor or the driver support hardware y-flipped blitting. --- glamor/glamor_core.c | 111 +++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 62 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 5f13b56d2..635b72641 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -289,7 +289,7 @@ 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, read_stride, x, y; + unsigned int stride, row_length, x, y; GLenum format, type; uint8_t *data, *read; glamor_screen_private *glamor_priv = @@ -307,15 +307,14 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) } stride = pixmap->devKind; - read_stride = stride; - - data = malloc(stride * pixmap->drawable.height); + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + switch (drawable->depth) { case 1: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; - read_stride = pixmap->drawable.width; + row_length = stride; break; case 8: format = GL_ALPHA; @@ -330,67 +329,47 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) break; default: ErrorF("Unknown prepareaccess depth %d\n", drawable->depth); - free(data); return FALSE; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); glPixelStorei(GL_PACK_ALIGNMENT, 1); - if (drawable->depth != 1) { - glPixelStorei(GL_PACK_ROW_LENGTH, read_stride * 8 / - pixmap->drawable.bitsPerPixel); + 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 { - glPixelStorei(GL_PACK_ROW_LENGTH, read_stride); - } - if (GLEW_MESA_pack_invert && drawable->depth != 1) { - if (!glamor_priv->yInverted) - glPixelStorei(GL_PACK_INVERT_MESA, 1); - glReadPixels(0, 0, - pixmap->drawable.width, pixmap->drawable.height, - format, type, data); - if (!glamor_priv->yInverted) - glPixelStorei(GL_PACK_INVERT_MESA, 0); - } else { - glGenBuffersARB(1, &pixmap_priv->pbo); + 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, - read_stride * pixmap->drawable.height, - NULL, GL_STREAM_READ_ARB); - glReadPixels(0, 0, - pixmap->drawable.width, pixmap->drawable.height, - format, type, 0); - + 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); - if (pixmap->drawable.depth == 1) { - for (y = 0; y < pixmap->drawable.height; y++) { - uint8_t *read_row; - uint8_t *write_row = data + y * stride; - - if (glamor_priv->yInverted) - read_row = read + read_stride * y; - else - read_row = read + - read_stride * (pixmap->drawable.height - y - 1); - - for (x = 0; x < pixmap->drawable.width; x++) { - int index = x / 8; - int bit = 1 << (x % 8); - - if (read_row[x]) - write_row[index] |= bit; - else - write_row[index] &= ~bit; - } - } - } else { - for (y = 0; y < pixmap->drawable.height; y++) - if (glamor_priv->yInverted) - memcpy(data + y * stride, read + y * stride, stride); - else - memcpy(data + y * stride, - read + (pixmap->drawable.height - y - 1) * stride, stride); - } + 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); @@ -452,7 +431,7 @@ glamor_finish_access(DrawablePtr drawable) glamor_get_screen_private(drawable->pScreen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - unsigned int stride; + unsigned int stride, row_length; GLenum format, type; static float vertices[4][2] = {{-1, -1}, { 1, -1}, @@ -489,10 +468,13 @@ glamor_finish_access(DrawablePtr drawable) if (pixmap->devPrivate.ptr == NULL) return; + stride = pixmap->devKind; + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; switch (drawable->depth) { case 1: format = GL_COLOR_INDEX; type = GL_BITMAP; + row_length = stride; break; case 8: format = GL_ALPHA; @@ -510,7 +492,6 @@ glamor_finish_access(DrawablePtr drawable) return; } - stride = pixmap->devKind; glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -523,8 +504,7 @@ glamor_finish_access(DrawablePtr drawable) glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8 / - pixmap->drawable.bitsPerPixel); + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glGenTextures(1, &tex); glActiveTexture(GL_TEXTURE0); @@ -540,14 +520,21 @@ glamor_finish_access(DrawablePtr drawable) glUseProgramObjectARB(glamor_priv->finish_access_prog); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisable(GL_TEXTURE_2D); glUseProgramObjectARB(0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); - free(pixmap->devPrivate.ptr); + if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { + glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT); + glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); + glDeleteBuffersARB (1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; + } else + free(pixmap->devPrivate.ptr); + pixmap->devPrivate.ptr = NULL; } From 1edf0cc6ab340c98fde201328631ca61e9d871a1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 22 May 2011 23:45:51 +0800 Subject: [PATCH 121/462] glamor: Don't write back read only pixmap to fbo. For those pixmap which has valid fbo and opened as GLAMOR_ACCESS_RO mode, we don't need to upload the texture back when calling the glamor_finish_access(). This will get about 10% performance gain. --- glamor/glamor_core.c | 5 +++++ glamor/glamor_priv.h | 1 + 2 files changed, 6 insertions(+) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 635b72641..f5fc1a3eb 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -332,6 +332,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) 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); @@ -468,6 +469,9 @@ glamor_finish_access(DrawablePtr drawable) if (pixmap->devPrivate.ptr == NULL) return; + if (pixmap_priv->access_mode == GLAMOR_ACCESS_RO) + goto read_only; + stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; switch (drawable->depth) { @@ -526,6 +530,7 @@ glamor_finish_access(DrawablePtr drawable) glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); +read_only: if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 93837e0b7..8ded91a5e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -193,6 +193,7 @@ typedef struct glamor_pixmap_private { GLuint fb; GLuint pbo; enum glamor_pixmap_type type; + glamor_access_t access_mode; } glamor_pixmap_private; extern DevPrivateKey glamor_screen_private_key; From 28835be1b8a05e510aa7fcc2f331771e3cf7dfec Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 24 May 2011 22:01:49 +0800 Subject: [PATCH 122/462] glamor: improve glamor_finish_access. When the platform's coordinate system is the same as X11's . We can load the texture to the fbo directly without one extra texture transformation. --- glamor/glamor_core.c | 148 +++++++++++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 48 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f5fc1a3eb..d41b26db7 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -425,56 +425,21 @@ glamor_init_finish_access_shaders(ScreenPtr screen) } } -void -glamor_finish_access(DrawablePtr drawable) +/* Load the pixmap's data to the fbo's texutre directly. + * Only useful when the platform enable yInverted, for + * example MESA/EGL. + * */ +void glamor_load_texture_pixmap_direct(PixmapPtr pixmap) { - 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); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); unsigned int stride, row_length; GLenum format, type; - static float vertices[4][2] = {{-1, -1}, - { 1, -1}, - { 1, 1}, - {-1, 1}}; - static float texcoords[4][2] = {{0, 1}, - {1, 1}, - {1, 0}, - {0, 0}}; - - GLuint tex; - static float texcoords_inverted[4][2] = {{0, 0}, - {1, 0}, - {1, 1}, - {0, 1}}; - static float *ptexcoords; - - if (pixmap_priv == NULL) - return; - if (glamor_priv->yInverted) - ptexcoords = &texcoords_inverted[0][0]; - else - ptexcoords = &texcoords[0][0]; - - if (pixmap_priv->fb == 0) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - - if (pixmap != screen_pixmap) - return; - } - - /* Check if finish_access was already called once on this */ - if (pixmap->devPrivate.ptr == NULL) - return; - - if (pixmap_priv->access_mode == GLAMOR_ACCESS_RO) - goto read_only; stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - switch (drawable->depth) { + switch (pixmap->drawable.depth) { case 1: format = GL_COLOR_INDEX; type = GL_BITMAP; @@ -485,23 +450,80 @@ glamor_finish_access(DrawablePtr drawable) type = GL_UNSIGNED_BYTE; break; case 24: - assert(drawable->bitsPerPixel == 32); + assert(pixmap->drawable.bitsPerPixel == 32); /* FALLTHROUGH */ case 32: format = GL_BGRA; type = GL_UNSIGNED_INT_8_8_8_8_REV; break; default: - ErrorF("Unknown finishaccess depth %d\n", drawable->depth); + ErrorF("Unknown finishaccess depth %d\n", pixmap->drawable.depth); return; } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + pixmap->drawable.width, pixmap->drawable.height, 0, + format, type, pixmap->devPrivate.ptr); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + + +/* + * Load texture from the pixmap's data pointer and then + * draw the texture to the fbo, and flip the y axis. + * */ +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}; + GLuint tex; + + stride = pixmap->devKind; + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + switch (pixmap->drawable.depth) { + case 1: + format = GL_COLOR_INDEX; + type = GL_BITMAP; + row_length = stride; + break; + case 8: + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; + break; + case 24: + assert(pixmap->drawable.bitsPerPixel == 32); + /* FALLTHROUGH */ + 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); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); @@ -529,8 +551,39 @@ glamor_finish_access(DrawablePtr drawable) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); +} + +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); + unsigned int stride, row_length; + GLenum format, type; + /* Check if finish_access was already called once on this */ + if (pixmap->devPrivate.ptr == NULL) + return; + + if (pixmap_priv == NULL) + return; + + if (pixmap_priv->fb == 0) { + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + + if (pixmap != screen_pixmap) + return; + } + + if (pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { + if (glamor_priv->yInverted) + glamor_load_texture_pixmap_direct(pixmap); + else + glamor_load_texture_pixmap(pixmap); + } -read_only: if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT); @@ -542,7 +595,6 @@ read_only: pixmap->devPrivate.ptr = NULL; } - /** * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the * current fill style. From b8ce483f58112f200dec9853fcd7ff455479990f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 1 Jun 2011 17:54:01 +0800 Subject: [PATCH 123/462] glamor: Don't use glamor_pixmap_type currently. Added comments to glamor_pixmap_create. To be refined in the future. We need to identify whether a pixmap is a CPU memory pixmap or a GPU pixmap. Current implementation is not correct. There are three cases: 1. Too large pixmap, we direct it to CPU memory pixmap. 2. w ==0 || h == 0 pixmap, this case has two possibilities: 2.1 It will become a screen pixmap latter, then it should be GPU type. 2.2 It's a scratch pixmap or created from a share memory, then it should belong to CPU memory. XXX, need to be refined latter. --- glamor/glamor.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 4594f145c..42e398646 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -67,6 +67,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) glamor_pixmap_private *pixmap_priv; pixmap_priv = glamor_get_pixmap_private(pixmap); + assert(pixmap_priv); pixmap_priv->tex = tex; /* Create a framebuffer object wrapping the texture so that we can render @@ -87,6 +88,12 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) } +/* 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, @@ -96,7 +103,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, GLenum format; GLuint tex; glamor_pixmap_private *pixmap_priv; - int type = GLAMOR_GL; + enum glamor_pixmap_type type = GLAMOR_GL; if (w > 32767 || h > 32767) return NullPixmap; @@ -111,7 +118,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, 7) / 8) + 3) & ~3, NULL); ErrorF("fallback to software fb for pixmap %p , %d x %d \n", pixmap, w, h); - } else + } else pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { @@ -120,12 +127,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; } - if (w == 0 || h == 0 || type != GLAMOR_GL) + if (w == 0 || h == 0 || type == GLAMOR_FB) return pixmap; - pixmap_priv = glamor_get_pixmap_private(pixmap); - pixmap_priv->type = type; - /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. * FBOs, which EXT_fbo forgot to do. */ From 925fc9724ff72d9e2a4940d7a1e39c23fb3ec9f0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 1 Jun 2011 18:02:03 +0800 Subject: [PATCH 124/462] glamor: Optimize glamor_finish_access. use pbo if possible when we load texture to a temporary tex. And for the previous direct texture load function, it's not correct and get removed in this commit. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 103 +++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 67 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index d41b26db7..f9e43c50c 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -295,7 +295,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (pixmap_priv == NULL) + if (!pixmap_priv) return TRUE; if (pixmap_priv->fb == 0) { @@ -425,53 +425,6 @@ glamor_init_finish_access_shaders(ScreenPtr screen) } } -/* Load the pixmap's data to the fbo's texutre directly. - * Only useful when the platform enable yInverted, for - * example MESA/EGL. - * */ -void glamor_load_texture_pixmap_direct(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; - - stride = pixmap->devKind; - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - switch (pixmap->drawable.depth) { - case 1: - format = GL_COLOR_INDEX; - type = GL_BITMAP; - row_length = stride; - break; - case 8: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case 24: - assert(pixmap->drawable.bitsPerPixel == 32); - /* FALLTHROUGH */ - 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; - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - pixmap->drawable.width, pixmap->drawable.height, 0, - format, type, pixmap->devPrivate.ptr); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -} - - /* * Load texture from the pixmap's data pointer and then * draw the texture to the fbo, and flip the y axis. @@ -493,8 +446,18 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) 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; + if (glamor_priv->yInverted) + ptexcoords = texcoords_inverted; + stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; switch (pixmap->drawable.depth) { @@ -523,7 +486,7 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) glEnableClientState(GL_VERTEX_ARRAY); glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, ptexcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); @@ -535,9 +498,18 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) 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, pixmap->devPrivate.ptr); + 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); @@ -560,13 +532,11 @@ glamor_finish_access(DrawablePtr drawable) glamor_get_screen_private(drawable->pScreen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - unsigned int stride, row_length; - GLenum format, type; /* Check if finish_access was already called once on this */ if (pixmap->devPrivate.ptr == NULL) return; - if (pixmap_priv == NULL) + if (!pixmap_priv) return; if (pixmap_priv->fb == 0) { @@ -577,21 +547,20 @@ glamor_finish_access(DrawablePtr drawable) return; } - if (pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { - if (glamor_priv->yInverted) - glamor_load_texture_pixmap_direct(pixmap); - else - glamor_load_texture_pixmap(pixmap); - } - if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT); - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); - glDeleteBuffersARB (1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; - } else - free(pixmap->devPrivate.ptr); + 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); + glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT); + 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; } From 0e2af4d0c942405dd0869f1e6a1effee943de139 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 1 Jun 2011 18:14:01 +0800 Subject: [PATCH 125/462] glamor: Don't print those fallback messages by default. Signed-off-by: Zhigang Gong --- glamor/glamor_priv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 8ded91a5e..d88626f51 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -231,8 +231,8 @@ glamor_fallback(char *format, ...) va_list ap; va_start(ap, format); - LogMessageVerb(X_INFO, 0, "fallback: "); - LogVMessageVerb(X_NONE, 0, format, ap); + LogMessageVerb(X_INFO, 3, "fallback: "); + LogMessageVerb(X_NONE, 3, format, ap); va_end(ap); } @@ -265,8 +265,8 @@ 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, 0, "fallback: %s", - // glamor_priv->delayed_fallback_string); + LogMessageVerb(X_INFO, 3, "fallback: %s", + glamor_priv->delayed_fallback_string); glamor_clear_delayed_fallbacks(screen); } } From 3c44e3e0ce1e286e0540298d5db547c43903629f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 1 Jun 2011 19:35:15 +0800 Subject: [PATCH 126/462] glamor: Optimize composite when soure/mask is xrgb. Added a new shader aswizlle_prog to wired the alpha to 1 when the image color depth is 24 (xrgb). Then we don't need to fallback the xrgb source/mask to software composite in render phase. Also don't wire the alpha bit to 1 in the render phase. This can get about 2x performance gain with the cairo performance trace's firefox-planet case. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 41 ++++++++++++++++++++++++++++++++++------ glamor/glamor_priv.h | 1 + glamor/glamor_putimage.c | 9 ++++++--- glamor/glamor_render.c | 24 ++++------------------- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f9e43c50c..0bfa7600a 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -289,7 +289,7 @@ 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, x, y; + unsigned int stride, row_length, y; GLenum format, type; uint8_t *data, *read; glamor_screen_private *glamor_priv = @@ -399,20 +399,38 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "{\n" " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" "}\n"; - GLint fs_prog, vs_prog; + + 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; glamor_priv->finish_access_prog = glCreateProgramObjectARB(); + glamor_priv->aswizzle_prog = 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); + + 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"); } glamor_link_glsl_prog(glamor_priv->finish_access_prog); + glamor_link_glsl_prog(glamor_priv->aswizzle_prog); if (GLEW_ARB_fragment_shader) { GLint sampler_uniform_location; @@ -422,6 +440,12 @@ glamor_init_finish_access_shaders(ScreenPtr screen) 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); } } @@ -429,7 +453,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) * Load texture from the pixmap's data pointer and then * draw the texture to the fbo, and flip the y axis. * */ -void +static void glamor_load_texture_pixmap(PixmapPtr pixmap) { @@ -454,9 +478,12 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) void * texel; GLuint tex; + int alfa_mode = 0; if (glamor_priv->yInverted) ptexcoords = texcoords_inverted; + else + ptexcoords = texcoords; stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; @@ -473,6 +500,7 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) 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; @@ -515,7 +543,10 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) glEnable(GL_TEXTURE_2D); assert(GLEW_ARB_fragment_shader); - glUseProgramObjectARB(glamor_priv->finish_access_prog); + 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); @@ -547,14 +578,12 @@ glamor_finish_access(DrawablePtr drawable) 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); - glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT); glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT, 0); glDeleteBuffersARB (1, &pixmap_priv->pbo); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index d88626f51..8c9ff857c 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -159,6 +159,7 @@ typedef struct glamor_screen_private { /* glamor_finishaccess */ GLint finish_access_prog; + GLint aswizzle_prog; /* glamor_solid */ GLint solid_prog; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 6a9c1aa60..f1081b055 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -256,7 +256,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int x_off, y_off; float vertices[4][2], texcoords[4][2]; GLuint tex; - + int alfa_mode = 0; if (image_format == XYBitmap) { assert(depth == 1); glamor_put_image_xybitmap(drawable, gc, x, y, w, h, @@ -299,6 +299,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, case 24: assert(drawable->bitsPerPixel == 32); /* FALLTHROUGH */ + alfa_mode = 1; case 32: format = GL_BGRA; type = GL_UNSIGNED_INT_8_8_8_8_REV; @@ -340,8 +341,10 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glEnable(GL_TEXTURE_2D); assert(GLEW_ARB_fragment_shader); - glUseProgramObjectARB(glamor_priv->finish_access_prog); - + if (alfa_mode == 0) + glUseProgramObjectARB(glamor_priv->finish_access_prog); + else + glUseProgramObjectARB(glamor_priv->aswizzle_prog); x += drawable->x; y += drawable->y; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6139b0d02..e69d370d9 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -86,8 +86,7 @@ glamor_create_composite_fs(struct shader_key *key) "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" "{\n" - " return vec4(texture2D(source_sampler, gl_TexCoord[0].xy).rgb,\n" - " 1.0);\n" + " return texture2D(source_sampler, gl_TexCoord[0].xy);\n" "}\n"; const char *mask_solid_fetch = "uniform vec4 mask;\n" @@ -105,8 +104,7 @@ glamor_create_composite_fs(struct shader_key *key) "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" - " return vec4(texture2D(mask_sampler, gl_TexCoord[1].xy).rgb, \n" - " 1.0);\n" + " return texture2D(mask_sampler, gl_TexCoord[1].xy);\n" "}\n"; const char *in_source_only = "void main()\n" @@ -495,15 +493,8 @@ good_source_format(PicturePtr picture) case PICT_a1: case PICT_a8: case PICT_a8r8g8b8: - return TRUE; case PICT_x8r8g8b8: - /* In order to support formats with no alpha, we have to wire the - * alpha to 1 in the shader, which conflicts with - * GL_CLAMP_TO_BORDERing to transparent. We could possibly compute - * coverage of the texels in the sampling area if we need to, but - * that isn't implemented today. - */ - return (picture->repeatType != RepeatNone); + return TRUE; default: glamor_fallback("Bad source format 0x%08x\n", picture->format); return FALSE; @@ -517,15 +508,8 @@ good_mask_format(PicturePtr picture) case PICT_a1: case PICT_a8: case PICT_a8r8g8b8: - return TRUE; case PICT_x8r8g8b8: - /* In order to support formats with no alpha, we have to wire the - * alpha to 1 in the shader, which conflicts with - * GL_CLAMP_TO_BORDERing to transparent. We could possibly compute - * coverage of the texels in the sampling area if we need to, but - * that isn't implemented today. - */ - return (picture->repeatType != RepeatNone); + return TRUE; default: glamor_fallback("Bad mask format 0x%08x\n", picture->format); return FALSE; From ac0589c91699433bc9dbc25b7edff456dff742a4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 14:02:19 +0800 Subject: [PATCH 127/462] glamor: Use software fb for 1bpp pixmap. For 1bpp pixmap, software fb get better performance than GL surface. The main reason is that fbo doesn't support 1bpp texture as internal format, so we have to translate a 1bpp bitmap to a 8bit alpha format each time which is very inefficient. And the previous implementation is not supported by the latest OpenGL 4.0, the GL_BITMAP was deprecated. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 5 +++-- glamor/glamor_core.c | 13 ++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 42e398646..be5999a0c 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -108,7 +108,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; - if (w > MAX_WIDTH || h > MAX_HEIGHT) { + if (w > MAX_WIDTH || h > MAX_HEIGHT || ( depth == 1 && w != 0 && h != 0)) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. If we exceed such limitation, we have to use framebuffer.*/ type = GLAMOR_FB; @@ -117,7 +117,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, NULL); - ErrorF("fallback to software fb for pixmap %p , %d x %d \n", pixmap, w, h); + + glamor_fallback("fallback to software fb for pixmap %p , %d x %d depth %d\n", pixmap, w, h, depth); } else pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 0bfa7600a..14031d276 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -309,13 +309,8 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - + assert(drawable->depth != 1); switch (drawable->depth) { - case 1: - format = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - row_length = stride; - break; case 8: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; @@ -485,14 +480,10 @@ glamor_load_texture_pixmap(PixmapPtr pixmap) else ptexcoords = texcoords; + assert(pixmap->drawable.depth != 1); stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; switch (pixmap->drawable.depth) { - case 1: - format = GL_COLOR_INDEX; - type = GL_BITMAP; - row_length = stride; - break; case 8: format = GL_ALPHA; type = GL_UNSIGNED_BYTE; From 229240e565f976de8e7b82dd606c2e862152b2b5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 14:07:54 +0800 Subject: [PATCH 128/462] glamor: Add render triangles support. By default, fallback to frame buffer currently. This commit makes us pass the rendercheck's triangles testing. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor.c | 3 ++ glamor/glamor_priv.h | 20 ++++++++++--- glamor/glamor_triangles.c | 61 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 glamor/glamor_triangles.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index e823234ae..8f6292020 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -30,6 +30,7 @@ libglamor_la_SOURCES = \ glamor_setspans.c \ glamor_render.c \ glamor_tile.c \ + glamor_triangles.c\ glamor.h libglamor_la_LIBADD = \ glu3/libglu3.la diff --git a/glamor/glamor.c b/glamor/glamor.c index be5999a0c..7eebba39a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -279,6 +279,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) ps->Trapezoids = glamor_trapezoids; glamor_priv->saved_glyphs = ps->Glyphs; ps->Glyphs = glamor_glyphs; + glamor_priv->saved_triangles = ps->Triangles; + ps->Triangles = glamor_triangles; glamor_init_composite_shaders(screen); #endif glamor_init_solid_shader(screen); @@ -317,6 +319,7 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->Composite = glamor_priv->saved_composite; ps->Trapezoids = glamor_priv->saved_trapezoids; ps->Glyphs = glamor_priv->saved_glyphs; + ps->Triangles = glamor_priv->saved_triangles; } #endif free(glamor_priv); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 8c9ff857c..9f1679269 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -148,6 +148,7 @@ typedef struct glamor_screen_private { ChangeWindowAttributesProcPtr saved_change_window_attributes; CopyWindowProcPtr saved_copy_window; BitmapToRegionProcPtr saved_bitmap_to_region; + TrianglesProcPtr saved_triangles; char *delayed_fallback_string; int yInverted; @@ -232,8 +233,8 @@ glamor_fallback(char *format, ...) va_list ap; va_start(ap, format); - LogMessageVerb(X_INFO, 3, "fallback: "); - LogMessageVerb(X_NONE, 3, format, ap); + //LogMessageVerb(X_INFO, 3, "fallback: "); + //LogMessageVerb(X_NONE, 3, format, ap); va_end(ap); } @@ -266,8 +267,8 @@ 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); + //LogMessageVerb(X_INFO, 3, "fallback: %s", + // glamor_priv->delayed_fallback_string); glamor_clear_delayed_fallbacks(screen); } } @@ -461,4 +462,15 @@ void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int tile_x, int tile_y); void glamor_init_tile_shader(ScreenPtr screen); +/* glamor_triangles */ +void +glamor_triangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntris, + xTriangle *tris); + #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c new file mode 100644 index 000000000..168d485f0 --- /dev/null +++ b/glamor/glamor_triangles.c @@ -0,0 +1,61 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +void +glamor_triangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntris, + xTriangle *tris) +{ + + if (glamor_prepare_access(pDst->pDrawable, GLAMOR_ACCESS_RW)) { + if (pSrc->pDrawable == NULL || + glamor_prepare_access(pSrc->pDrawable, GLAMOR_ACCESS_RO)) + { + + fbTriangles(op, + pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris); + } + if (pSrc->pDrawable != NULL) + glamor_finish_access(pSrc->pDrawable); + + glamor_finish_access(pDst->pDrawable); + } +} + + From b60e6cb66d3fba43d5403b2b5027537d09ee7c98 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 15:46:23 +0800 Subject: [PATCH 129/462] glamor: Silence compilation warnings. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 - glamor/glamor.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 7eebba39a..d6d6d950a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -102,7 +102,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, PixmapPtr pixmap; GLenum format; GLuint tex; - glamor_pixmap_private *pixmap_priv; enum glamor_pixmap_type type = GLAMOR_GL; if (w > 32767 || h > 32767) diff --git a/glamor/glamor.h b/glamor/glamor.h index 33610a668..c49662e89 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -34,6 +34,7 @@ #include "gcstruct.h" #include "picturestr.h" #include "fb.h" +#include "fbpict.h" #endif /* GLAMOR_H */ From d7f8b888d0961af8d0ec6ad5c920ce758529b620 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 16:01:40 +0800 Subject: [PATCH 130/462] glamor: For non-supported fill style fallback to fbFill. The previous implementation will just skip the rendering which is not good. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 8 +++++--- glamor/glamor_fill.c | 45 +++++++++++++++++++++++--------------------- glamor/glamor_priv.h | 6 +++--- glamor/glamor_tile.c | 11 +++++------ 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 14031d276..a517045a5 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -621,15 +621,17 @@ glamor_finish_access_gc(GCPtr gc) glamor_finish_access(&gc->stipple->drawable); } -void +Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel, unsigned long bg_pixel, int stipple_x, int stipple_y) { - 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; +// ErrorF("stubbed out stipple depth %d\n", pixmap->drawable.depth); +// glamor_solid_fail_region(pixmap, x, y, width, height); } GCOps glamor_gc_ops = { diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 8ea70d0cf..2b94934b6 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -42,23 +42,23 @@ glamor_fill(DrawablePtr drawable, { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); int x_off, y_off; - glamor_get_drawable_deltas(drawable, dst_pixmap, &x_off, &y_off); switch (gc->fillStyle) { case FillSolid: - glamor_solid(dst_pixmap, - x + x_off, - y + y_off, - width, - height, - gc->alu, - gc->planemask, - gc->fgPixel); + if (!glamor_solid(dst_pixmap, + x + x_off, + y + y_off, + width, + height, + gc->alu, + gc->planemask, + gc->fgPixel)) + goto fail; break; case FillStippled: case FillOpaqueStippled: - glamor_stipple(dst_pixmap, + if (!glamor_stipple(dst_pixmap, gc->stipple, x+ x_off, y + y_off, @@ -69,10 +69,12 @@ glamor_fill(DrawablePtr drawable, gc->fgPixel, gc->bgPixel, gc->patOrg.x + x_off, - gc->patOrg.y + y_off); + gc->patOrg.y + y_off)) + goto fail; + return; break; case FillTiled: - glamor_tile(dst_pixmap, + if (!glamor_tile(dst_pixmap, gc->tile.pixmap, x + x_off, y + y_off, @@ -81,12 +83,12 @@ glamor_fill(DrawablePtr drawable, gc->alu, gc->planemask, drawable->x + x - gc->patOrg.x, - drawable->y + y - gc->patOrg.y); + drawable->y + y - gc->patOrg.y)) + goto fail; break; } return; -#if 0 - fail: +fail: glamor_fallback("glamor_fill()"); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { @@ -95,7 +97,6 @@ glamor_fill(DrawablePtr drawable, } glamor_finish_access(drawable); } -#endif return; } @@ -140,7 +141,7 @@ glamor_init_solid_shader(ScreenPtr screen) glGetUniformLocationARB(glamor_priv->solid_prog, "color"); } -void +Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel) { @@ -154,12 +155,12 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, float vertices[4][2]; if (!glamor_set_destination_pixmap(pixmap)) - return; + goto fail; glamor_set_alu(alu); if (!glamor_set_planemask(pixmap, planemask)) { - ErrorF("Failedto set planemask in glamor_solid.\n"); - goto fail; - } + ErrorF("Failedto set planemask in glamor_solid.\n"); + goto fail; + } glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_color_4f_from_pixel(pixmap, fg_pixel, color); @@ -188,9 +189,11 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glDisableClientState(GL_VERTEX_ARRAY); glUseProgramObjectARB(0); + return TRUE; fail: glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); + return FALSE; } /* Highlight places where we're doing it wrong. */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 9f1679269..1dc2c42c5 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -350,7 +350,7 @@ const Bool glamor_get_drawable_location(const DrawablePtr drawable); void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int *x, int *y); Bool glamor_create_gc(GCPtr gc); -void glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, +Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel, unsigned long bg_pixel, @@ -376,7 +376,7 @@ void glamor_fill(DrawablePtr drawable, int y, int width, int height); -void glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, +Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel); void glamor_solid_fail_region(PixmapPtr pixmap, @@ -456,7 +456,7 @@ void glamor_composite_rects(CARD8 op, int nrect, glamor_composite_rect_t *rects); /* glamor_tile.c */ -void glamor_tile(PixmapPtr pixmap, PixmapPtr tile, +Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, int tile_x, int tile_y); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 58923701e..5b1e73d5a 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -72,7 +72,7 @@ glamor_init_tile_shader(ScreenPtr screen) glUseProgramObjectARB(0); } -void +Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, @@ -93,7 +93,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, float source_texcoords[4][2]; if (glamor_priv->tile_prog == 0) { - ErrorF("Tiling unsupported\n"); + glamor_fallback("Tiling unsupported\n"); goto fail; } @@ -101,7 +101,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, goto fail; if (tile_priv->tex == 0) { - ErrorF("Non-texture tile pixmap\n"); + glamor_fallback("Non-texture tile pixmap\n"); goto fail; } @@ -167,9 +167,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glDisable(GL_TEXTURE_2D); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); - return; + return TRUE; fail: - glamor_solid_fail_region(pixmap, x, y, width, height); - return; + return FALSE; } From a0a52be73994c93521e94f1f10152ce851485ea3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 16:51:27 +0800 Subject: [PATCH 131/462] glamor: Fallback to fbPolylines for diagonal poly_line. It's better to give a correct output when we haven't implement all the code path. Signed-off-by: Zhigang Gong --- glamor/glamor_polylines.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index c9752685f..75bc9bf9a 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -76,17 +76,13 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, x2 = points[i + 1].x; y2 = points[i + 1].y; } - if (x1 != x2 && y1 != y2) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - free(rects); - - ErrorF("stub diagonal poly_line\n"); - glamor_solid_fail_region(pixmap, x1, y1, x2 - x1, y2 - y1); + glamor_fallback("stub diagonal poly_line\n"); + goto fail; return; } - if (x1 < x2) { rects[i].x = x1; rects[i].width = x2 - x1 + 1; From ba6dd8aa492d9d555d8b175bcf350e5db1821597 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 18:32:15 +0800 Subject: [PATCH 132/462] glamor: Simplify fill acceleration for spans/polyfillrect by only clipping once. This commit was borrowed from uxa driver contributed by Eric. commit number is e0066e77e026b0dd0daa0c3765473c7d63aa6753. commit log paste as below: We were clipping each span against the bounds of the clip, throwing out the span early if it was all clipped, and then walked the clip box clipping against each of the cliprects. We would expect spans to typically be clipped against one box, and not thrown out, so we were not saving any work there. For multiple cliprects, we were adding work. Only for many spans clipped entirely out of a complicated clip region would it have saved work, and it clearly didn't save bugs as evidenced by the many fix attempts here. Signed-off-by: Zhigang Gong --- glamor/glamor_fillspans.c | 84 +++++++++++------------------ glamor/glamor_polyfillrect.c | 102 ++++++++++++++--------------------- 2 files changed, 73 insertions(+), 113 deletions(-) diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index a633b3066..c6976c376 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -38,68 +38,48 @@ glamor_fill_spans(DrawablePtr drawable, int *widths, int sorted) { - RegionPtr clip = gc->pCompositeClip; - BoxPtr extents, boxes; + DDXPointPtr ppt; int nbox; - int extentX1, extentX2, extentY1, extentY2; - int fullX1, fullX2, fullY1; - int partX1, partX2; + BoxPtr pbox; + int x1, x2, y; + int off_x, off_y; + RegionPtr pClip = fbGetCompositeClip(gc); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; - extents = REGION_EXTENTS(gc->pScreen, clip); - extentX1 = extents->x1; - extentY1 = extents->y1; - extentX2 = extents->x2; - extentY2 = extents->y2; - while (n--) { - fullX1 = points->x; - fullY1 = points->y; - fullX2 = fullX1 + *widths; - points++; - widths++; - if (fullY1 < extentY1 || extentY2 <= fullY1) - continue; + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + ppt = points; + while (n--) { + x1 = ppt->x; + y = ppt->y; + x2 = x1 + (int)*widths; + ppt++; + widths++; - if (fullX1 < extentX1) - fullX1 = extentX1; + nbox = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + while (nbox--) { + if (pbox->y1 > y || pbox->y2 <= y) + continue; - if (fullX2 > extentX2) - fullX2 = extentX2; + if (x1 < pbox->x1) + x1 = pbox->x1; - if (fullX1 >= fullX2) - continue; + if (x2 > pbox->x2) + x2 = pbox->x2; - nbox = REGION_NUM_RECTS (clip); - if (nbox == 1) { - glamor_fill(drawable, - gc, - fullX1, fullY1, fullX2-fullX1, 1); - } else { - boxes = REGION_RECTS(clip); - while(nbox--) - { - if (boxes->y1 <= fullY1 && fullY1 < boxes->y2) - { - partX1 = boxes->x1; - if (partX1 < fullX1) - partX1 = fullX1; - partX2 = boxes->x2; - if (partX2 > fullX2) - partX2 = fullX2; - if (partX2 > partX1) - { - glamor_fill(drawable, gc, - partX1, fullY1, - partX2 - partX1, 1); - } - } - boxes++; - } - } - } + if (x2 <= x1) + continue; + glamor_fill (drawable,gc, + x1 + off_x, y + off_y, + x2 - x1 , 1); + pbox++; + } + } return; fail: glamor_fallback("glamor_fillspans(): to %p (%c)\n", drawable, diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 29e9db537..660dc4a5b 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -43,80 +43,60 @@ glamor_poly_fill_rect(DrawablePtr drawable, int nrect, xRectangle *prect) { - RegionPtr clip = fbGetCompositeClip(gc); - register BoxPtr box; - BoxPtr pextent; - int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1, fullY2; - int partX1, partX2, partY1, partY2; int xorg, yorg; int n; + register BoxPtr pbox; + int off_x, off_y; + RegionPtr pClip = fbGetCompositeClip(gc); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; xorg = drawable->x; yorg = drawable->y; + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); - pextent = REGION_EXTENTS(gc->pScreen, clip); - extentX1 = pextent->x1; - extentY1 = pextent->y1; - extentX2 = pextent->x2; - extentY2 = pextent->y2; - while (nrect--) - { - fullX1 = prect->x + xorg; - fullY1 = prect->y + yorg; - fullX2 = fullX1 + (int)prect->width; - fullY2 = fullY1 + (int)prect->height; - prect++; + while (nrect--) { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int)prect->width; + fullY2 = fullY1 + (int)prect->height; + prect++; - if (fullX1 < extentX1) - fullX1 = extentX1; + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + /* + * clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect(), + * but rectangles may overlap each other here. + */ + while (n--) { + int x1 = fullX1; + int x2 = fullX2; + int y1 = fullY1; + int y2 = fullY2; - if (fullY1 < extentY1) - fullY1 = extentY1; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (pbox->y1 > y1) + y1 = pbox->y1; + if (pbox->y2 < y2) + y2 = pbox->y2; + pbox++; - if (fullX2 > extentX2) - fullX2 = extentX2; - - if (fullY2 > extentY2) - fullY2 = extentY2; - - if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) - continue; - n = REGION_NUM_RECTS(clip); - if (n == 1) { - glamor_fill(drawable, - gc, - fullX1, fullY1, fullX2-fullX1, fullY2-fullY1); - } else { - box = REGION_RECTS(clip); - /* clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect() - */ - while (n--) { - partX1 = box->x1; - if (partX1 < fullX1) - partX1 = fullX1; - partY1 = box->y1; - if (partY1 < fullY1) - partY1 = fullY1; - partX2 = box->x2; - if (partX2 > fullX2) - partX2 = fullX2; - partY2 = box->y2; - if (partY2 > fullY2) - partY2 = fullY2; - - box++; - - if (partX1 < partX2 && partY1 < partY2) - glamor_fill(drawable, gc, - partX1, partY1, - partX2 - partX1, partY2 - partY1); - } - } + if (x1 >= x2 || y1 >= y2) + continue; + glamor_fill(drawable, + gc, + x1 + off_x, + y1 + off_y, + x2 - x1, + y2 - y1); + } } return; From 355334fcd99e4dce62e2be1e27290c9a74ea944f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 21 Jun 2011 18:31:11 +0800 Subject: [PATCH 133/462] glamor : Add dynamic texture uploading feature. Major refactoring. 1. Rewrite the pixmap texture uploading and downloading functions. Add some new functions for both the prepare/finish access and the new performance feature dynamic texture uploading, which could download and upload the current image to/from a private texture/fbo. In the uploading or downloading phase, we need to handle two things: The first is the yInverted option, If it set, then we don't need to flip y. If not set, if it is from a dynamic texture uploading then we don't need to flip either if the current drawing process will flip it latter. If it is from finish_access, then we must flip the y axis. The second thing is the alpha channel hanlding, if the pixmap's format is something like x8a8r8g8, x1r5g5b5 which means it doesn't has alpha channel, but it do has those extra bits. Then we need to wire those bits to 1. 2. Add almost all the required picture format support. This is not as trivial as it looks like. The previous implementation only support GL_a8,GL_a8r8g8b8,GL_x8r8g8b8. All the other format, we have to fallback to cpu. The reason why we can't simply add those other color format is because the exists of picture. one drawable pixmap may has one or even more container pictures. The drawable pixmap's depth can't map to a specified color format, for example depth 16 can mapped to r5g6b5, x1r5g5b5, a1r5g5b5, or even b5g6r5. So we can't get get the color format just from the depth value. But the pixmap do not has a pict_format element. We have to make a new one in the pixmap private data structure. Reroute the CreatePicture to glamor_create_picture and then store the picture's format to the pixmap's private structure. This is not an ideal solution, as there may be more than one pictures refer to the same pixmap. Then we will have trouble. There is an example in glamor_composite_with_shader. The source and mask often share the same pixmap, but use different picture format. Our current solution is to combine those two different picture formats to one which will not lose any data. Then change the source's format to this new format and then upload the pixmap to texture once. It works. If we fail to find a matched new format then we fallback. There still is a potential problem, if two pictures refer to the same pixmap, and one of them destroy the picture, but the other still remained to be used latter. We don't handle that situation currently. To be fixed. 3. Dynamic texture uploading. This is a performance feature. Although we don't like the client to hold a pixmap data to shared memory and we can't accelerate it. And even worse, we may need to fallback all the required pixmaps to cpu memory and then process them on CPU. This feature is to mitigate this penalty. When the target pixmap has a valid gl fbo attached to it. But the other pixmaps are not. Then it will be more efficient to upload the other pixmaps to GPU and then do the blitting or rendering on GPU than fallback all the pixmaps to CPU. To enable this feature, I experienced a significant performance improvement in the Game "Mines" :). 4. Debug facility. Modify the debug output mechanism. Now add a new macro: glamor_debug_output(_level_, _format_,...) to conditional output some messages according to the environment variable GLAMOR_DEBUG. We have the following levels currently. exports GLAMOR_DEBUG to 3 will enable all the above messages. 5. Changes in pixmap private data structure. Add some for the full color format supports and relate it to the pictures which already described. Also Add the following new elements: gl_fbo - to indicates whether this pixmap is on gpu only. gl_tex - to indicates whether the tex is valid and is containing the pixmap's image originally. As we bring the dynamic pixmap uploading feature, so a cpu memory pixmap may also has a valid fbo or tex attached to it. So we will have to use the above new element to check it true type. After this commit, we can pass the rendercheck testing for all the picture formats. And is much much fater than fallback to cpu when doing rendercheck testing. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 2 + glamor/glamor.c | 117 +- glamor/glamor.h | 7 +- glamor/glamor_copyarea.c | 98 +- glamor/glamor_core.c | 866 +++++--------- glamor/glamor_debug.h | 67 ++ glamor/glamor_fill.c | 33 +- glamor/glamor_fillspans.c | 5 +- glamor/glamor_getspans.c | 65 +- glamor/glamor_glyphs.c | 2 + glamor/glamor_picture.c | 93 ++ glamor/glamor_pixmap.c | 483 ++++++++ glamor/glamor_polyfillrect.c | 7 +- glamor/glamor_polylines.c | 7 +- glamor/glamor_priv.h | 660 ++++++++--- glamor/glamor_putimage.c | 79 +- glamor/glamor_render.c | 1972 +++++++++++++++++--------------- glamor/glamor_setspans.c | 60 +- glamor/glamor_tile.c | 12 +- hw/kdrive/ephyr/ephyr_glamor.c | 2 +- hw/xfree86/glamor/glamor.c | 3 +- 21 files changed, 2676 insertions(+), 1964 deletions(-) create mode 100644 glamor/glamor_debug.h create mode 100644 glamor/glamor_picture.c create mode 100644 glamor/glamor_pixmap.c 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; From ca1908e11dcb56cb952f6bce55503e932aa9a27c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 22 Jun 2011 14:33:38 +0800 Subject: [PATCH 134/462] glamor: Concentrate and reduce some coords processing code. Concentrate the verties and texture coords processing code to a new file glamor_utils.h. Change most of the code to macro. Will have some performance benefit on slow machine. And reduce most of the duplicate code when calculate the normalized coords. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 52 +++++++--------- glamor/glamor_fill.c | 32 ++++------ glamor/glamor_getspans.c | 16 +++-- glamor/glamor_priv.h | 41 +------------ glamor/glamor_putimage.c | 106 +++++++++++++++------------------ glamor/glamor_render.c | 119 ++++++++++++------------------------- glamor/glamor_tile.c | 72 +++++++++++------------ glamor/glamor_utils.h | 124 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 287 insertions(+), 275 deletions(-) create mode 100644 glamor/glamor_utils.h diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 766c9e2b3..55437715a 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -199,11 +199,13 @@ glamor_copy_n_to_n_textured(DrawablePtr src, PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int i; - float vertices[4][2], texcoords[4][2]; + float vertices[8], texcoords[8]; glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; int src_x_off, src_y_off, dst_x_off, dst_y_off; enum glamor_pixmap_status src_status = GLAMOR_NONE; + GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); @@ -237,6 +239,9 @@ glamor_copy_n_to_n_textured(DrawablePtr src, } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + 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); @@ -258,42 +263,25 @@ glamor_copy_n_to_n_textured(DrawablePtr src, assert(GLEW_ARB_fragment_shader); glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); + for (i = 0; i < nbox; i++) { - vertices[0][0] = v_from_x_coord_x(dst_pixmap, box[i].x1 + dst_x_off); - vertices[1][0] = v_from_x_coord_x(dst_pixmap, box[i].x2 + dst_x_off); - vertices[2][0] = v_from_x_coord_x(dst_pixmap, box[i].x2 + dst_x_off); - vertices[3][0] = v_from_x_coord_x(dst_pixmap, box[i].x1 + dst_x_off); - texcoords[0][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); - texcoords[1][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); - texcoords[2][0] = t_from_x_coord_x(src_pixmap, box[i].x2 + dx); - texcoords[3][0] = t_from_x_coord_x(src_pixmap, box[i].x1 + dx); + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, + box[i].x1 + dst_x_off, + box[i].y1 + dst_y_off, + box[i].x2 + dst_x_off, + box[i].y2 + dst_y_off, + glamor_priv->yInverted, + vertices); - if(glamor_priv->yInverted) { + glamor_set_normalize_tcoords(src_xscale, src_yscale, + box[i].x1 + dx, box[i].y1 + dy, + box[i].x2 + dx, box[i].y2 + dy, + glamor_priv->yInverted, + texcoords); - vertices[0][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y1 + dst_y_off); - vertices[1][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y1 + dst_y_off); - vertices[2][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y2 + dst_y_off); - vertices[3][1] = v_from_x_coord_y_inverted(dst_pixmap, box[i].y2 + dst_y_off); - - texcoords[0][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y1 + dy); - texcoords[1][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y1 + dy); - texcoords[2][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y2 + dy); - texcoords[3][1] = t_from_x_coord_y_inverted(src_pixmap, box[i].y2 + dy); - } else { - - vertices[0][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); - vertices[1][1] = v_from_x_coord_y(dst_pixmap, box[i].y1 + dst_y_off); - vertices[2][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); - vertices[3][1] = v_from_x_coord_y(dst_pixmap, box[i].y2 + dst_y_off); - - texcoords[0][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); - texcoords[1][1] = t_from_x_coord_y(src_pixmap, box[i].y1 + dy); - texcoords[2][1] = t_from_x_coord_y(src_pixmap, box[i].y2 + dy); - texcoords[3][1] = t_from_x_coord_y(src_pixmap, box[i].y2 + dy); - } - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } glUseProgramObjectARB(0); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index fade2b3cd..48f85ce38 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -146,14 +146,16 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int x1 = x; int x2 = x + width; int y1 = y; int y2 = y + height; GLfloat color[4]; - float vertices[4][2]; - - if (glamor_set_destination_pixmap(pixmap)) { + float vertices[8]; + GLfloat xscale, yscale; + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; } @@ -162,6 +164,9 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_fallback("Failedto set planemask in glamor_solid.\n"); goto fail; } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_rgba_from_pixel(fg_pixel, &color[0], @@ -174,22 +179,11 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - vertices[0][0] = v_from_x_coord_x(pixmap, x1); - vertices[1][0] = v_from_x_coord_x(pixmap, x2); - vertices[2][0] = v_from_x_coord_x(pixmap, x2); - vertices[3][0] = v_from_x_coord_x(pixmap, x1); - - if (glamor_priv->yInverted) { - vertices[0][1] = v_from_x_coord_y_inverted(pixmap, y1); - vertices[1][1] = v_from_x_coord_y_inverted(pixmap, y1); - vertices[2][1] = v_from_x_coord_y_inverted(pixmap, y2); - vertices[3][1] = v_from_x_coord_y_inverted(pixmap, y2); - } else { - vertices[0][1] = v_from_x_coord_y(pixmap, y1); - vertices[1][1] = v_from_x_coord_y(pixmap, y1); - vertices[2][1] = v_from_x_coord_y(pixmap, y2); - vertices[3][1] = v_from_x_coord_y(pixmap, y2); - } + pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + + glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, + glamor_priv->yInverted, + vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 10fa2a2c3..7fe05f993 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -42,11 +42,17 @@ 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); + glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int i; uint8_t *readpixels_dst = (uint8_t *)dst; int x_off, y_off; + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("pixmap has no fbo.\n"); + goto fail; + } + if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, @@ -57,10 +63,8 @@ glamor_get_spans(DrawablePtr drawable, goto fail; } - if (glamor_set_destination_pixmap(pixmap)) { - glamor_fallback("pixmap has no fbo.\n"); - goto fail; - } + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); for (i = 0; i < count; i++) { if (glamor_priv->yInverted) { diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index cf293b5dc..5b457e7fc 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -505,44 +505,6 @@ glamor_pm_is_solid(DrawablePtr drawable, unsigned long planemask) 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; -} - -static inline float -v_from_x_coord_y(PixmapPtr pixmap, int y) -{ - 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; -} - - -static inline float -t_from_x_coord_x(PixmapPtr pixmap, int x) -{ - 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; -} - -static inline float -t_from_x_coord_y_inverted(PixmapPtr pixmap, int y) -{ - return (float)y / pixmap->drawable.height; -} - - /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); @@ -791,4 +753,7 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD + +#include"glamor_utils.h" + #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index d056576a0..e61425d11 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -87,17 +87,6 @@ glamor_init_putimage_shaders(ScreenPtr screen) glUseProgramObjectARB(0); } -static int -y_flip(PixmapPtr pixmap, int y) -{ - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - - if (pixmap == screen_pixmap) - return (pixmap->drawable.height - 1) - y; - else - return y; -} /* Do an XYBitmap putimage. The bits are byte-aligned rows of bitmap * data (where each row starts at a bit index of left_pad), and the @@ -110,6 +99,21 @@ y_flip(PixmapPtr pixmap, int y) * case we might be better off just doing the fg/bg choosing in the CPU * and just draw the resulting texture to the destination. */ +#if 0 + +static int +y_flip(PixmapPtr pixmap, int y) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + + if (pixmap == screen_pixmap) + return (pixmap->drawable.height - 1) - y; + else + return y; +} + + static void glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, int x, int y, int w, int h, int left_pad, @@ -124,25 +128,27 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, RegionPtr clip; BoxPtr box; int nbox; - float dest_coords[4][2]; + float dest_coords[8]; const float bitmap_coords[8] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, }; + GLfloat xscale, yscale; + glamor_pixmap_private *pixmap_priv; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); - 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); - dest_coords[1][1] = v_from_x_coord_y(pixmap, y); - dest_coords[2][0] = v_from_x_coord_x(pixmap, x + w); - dest_coords[2][1] = v_from_x_coord_y(pixmap, y + h); - dest_coords[3][0] = v_from_x_coord_x(pixmap, x); - dest_coords[3][1] = v_from_x_coord_y(pixmap, y + h); + glamor_set_normalize_vcoords(xscale, yscale, + x, y, + x + w, y + h, + glamor_priv->yInverted, + dest_coords); - glamor_fallback("glamor_put_image_xybitmap: disabled\n"); + glamor_fallback("glamor_put_image_xybitmap: disabled\n"); goto fail; if (glamor_priv->put_image_xybitmap_prog == 0) { @@ -237,6 +243,8 @@ fail: glamor_finish_access(drawable); } } +#endif + void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, @@ -252,13 +260,13 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int nbox; int src_stride = PixmapBytePad(w, drawable->depth); int x_off, y_off; - float vertices[4][2], texcoords[4][2]; + float vertices[8], texcoords[8]; + GLfloat xscale, yscale, txscale, tyscale; GLuint tex; int ax = 0; if (image_format == XYBitmap) { assert(depth == 1); - glamor_put_image_xybitmap(drawable, gc, x, y, w, h, - left_pad, image_format, bits); + goto fail; return; } @@ -319,8 +327,12 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, y += drawable->y; glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - clip = fbGetCompositeClip(gc); + + txscale = 1.0/w; + tyscale = 1.0/h; + pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + for (nbox = REGION_NUM_RECTS(clip), pbox = REGION_RECTS(clip); nbox--; @@ -330,7 +342,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int y1 = y; int x2 = x + w; int y2 = y + h; - float src_x1, src_x2, src_y1, src_y2; if (x1 < pbox->x1) x1 = pbox->x1; @@ -343,41 +354,18 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (x1 >= x2 || y1 >= y2) continue; - src_x1 = (float)(x1 - x) / w; - src_y1 = (float)(y1 - y) / h; - src_x2 = (float)(x2 - x) / w; - src_y2 = (float)(y2 - y) / h; + glamor_set_normalize_tcoords( txscale, tyscale, + x1 - x, y1 - y, + x2 - x, y2 - y, + 1, + texcoords); - vertices[0][0] = v_from_x_coord_x(pixmap, x1 + x_off); - vertices[1][0] = v_from_x_coord_x(pixmap, x2 + x_off); - vertices[2][0] = v_from_x_coord_x(pixmap, x2 + x_off); - vertices[3][0] = v_from_x_coord_x(pixmap, x1 + x_off); + glamor_set_normalize_vcoords( xscale, yscale, + x1 + x_off, y1 + y_off, + x2 + x_off, y2 + y_off, + glamor_priv->yInverted, + vertices); - texcoords[0][0] = src_x1; - texcoords[0][1] = src_y1; - texcoords[1][0] = src_x2; - texcoords[1][1] = src_y1; - texcoords[2][0] = src_x2; - texcoords[2][1] = src_y2; - texcoords[3][0] = src_x1; - texcoords[3][1] = src_y2; - - - if (glamor_priv->yInverted) { - - vertices[0][1] = v_from_x_coord_y_inverted(pixmap, y1 + y_off); - vertices[1][1] = v_from_x_coord_y_inverted(pixmap, y1 + y_off); - vertices[2][1] = v_from_x_coord_y_inverted(pixmap, y2 + y_off); - vertices[3][1] = v_from_x_coord_y_inverted(pixmap, y2 + y_off); - - } else { - - vertices[0][1] = v_from_x_coord_y(pixmap, y1 + y_off); - vertices[1][1] = v_from_x_coord_y(pixmap, y1 + y_off); - vertices[2][1] = v_from_x_coord_y(pixmap, y2 + y_off); - vertices[3][1] = v_from_x_coord_y(pixmap, y2 + y_off); - - } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index ca27b4d59..f991b0f17 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -533,41 +533,6 @@ good_dest_format(PicturePtr picture) } } -static inline float -xFixedToFloat(pixman_fixed_t val) -{ - 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); - - 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; - } - 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) { @@ -756,6 +721,8 @@ glamor_composite_with_shader(CARD8 op, glamor_pixmap_private *source_pixmap_priv = NULL; glamor_pixmap_private *mask_pixmap_priv = NULL; glamor_pixmap_private *dest_pixmap_priv = NULL; + GLfloat dst_xscale, dst_yscale; + GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; struct shader_key key; glamor_composite_shader *shader; RegionRec region; @@ -768,6 +735,8 @@ glamor_composite_with_shader(CARD8 op, enum glamor_pixmap_status source_status = GLAMOR_NONE; enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; + float src_matrix[9], mask_matrix[9]; + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { @@ -972,14 +941,24 @@ glamor_composite_with_shader(CARD8 op, glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, &dest_x_off, &dest_y_off); + pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + + + if (source_pixmap) { glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, &source_y_off); + pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); + glamor_picture_get_matrixf(source, src_matrix); } + if (mask_pixmap) { glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &mask_x_off, &mask_y_off); + pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); + glamor_picture_get_matrixf(mask, mask_matrix); } + while (nrect--) { INT16 x_source; INT16 y_source; @@ -1025,65 +1004,41 @@ glamor_composite_with_shader(CARD8 op, 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); + int vx1 = box[i].x1 + dest_x_off; + int vx2 = box[i].x2 + dest_x_off; + int vy1 = box[i].y1 + dest_y_off; + int vy2 = box[i].y2 + dest_y_off; + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, vx1, vy1, vx2, vy2, + glamor_priv->yInverted, vertices); - 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 (source->transform) + glamor_set_transformed_normalize_tcoords(src_matrix, src_xscale, src_yscale, + tx1, ty1, tx2, ty2, + glamor_priv->yInverted, + source_texcoords); + else + glamor_set_normalize_tcoords(src_xscale, src_yscale, tx1, ty1, tx2, ty2, + glamor_priv->yInverted, source_texcoords); + } 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 (mask->transform) + glamor_set_transformed_normalize_tcoords(mask_matrix, mask_xscale, mask_yscale, + tx1, ty1, tx2, ty2, + glamor_priv->yInverted, + mask_texcoords); + else + glamor_set_normalize_tcoords(mask_xscale, mask_yscale, tx1, ty1, tx2, ty2, + glamor_priv->yInverted, mask_texcoords); } glamor_emit_composite_rect(screen, source_texcoords, mask_texcoords, vertices); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 2991eddd5..90bf734be 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -88,70 +88,64 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int tile_x2 = tile_x + width; int tile_y1 = tile_y; int tile_y2 = tile_y + height; - glamor_pixmap_private *tile_priv = glamor_get_pixmap_private(tile); - float vertices[4][2]; - float source_texcoords[4][2]; + float vertices[8]; + float source_texcoords[8]; + GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; + glamor_pixmap_private *src_pixmap_priv; + glamor_pixmap_private *dst_pixmap_priv; + + src_pixmap_priv = glamor_get_pixmap_private(tile); + dst_pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; } - if (glamor_set_destination_pixmap(pixmap)) { - glamor_fallback("dest has no fbo."); - goto fail; + + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + glamor_fallback("dest has no fbo."); + goto fail; } - if (tile_priv->gl_tex == 0) { - glamor_fallback("Non-texture tile pixmap\n"); - goto fail; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { + /* XXX dynamic uploading candidate. */ + glamor_fallback("Non-texture tile pixmap\n"); + goto fail; } if (!glamor_set_planemask(pixmap, planemask)) { glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; } + + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + glamor_set_alu(alu); glUseProgramObjectARB(glamor_priv->tile_prog); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tile_priv->tex); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glEnable(GL_TEXTURE_2D); - vertices[0][0] = v_from_x_coord_x(pixmap, x1); - vertices[1][0] = v_from_x_coord_x(pixmap, x2); - vertices[2][0] = v_from_x_coord_x(pixmap, x2); - vertices[3][0] = v_from_x_coord_x(pixmap, x1); - source_texcoords[0][0] = t_from_x_coord_x(tile, tile_x1); - source_texcoords[1][0] = t_from_x_coord_x(tile, tile_x2); - source_texcoords[2][0] = t_from_x_coord_x(tile, tile_x2); - source_texcoords[3][0] = t_from_x_coord_x(tile, tile_x1); - - if (glamor_priv->yInverted) { - vertices[0][1] = v_from_x_coord_y_inverted(pixmap, y1); - vertices[1][1] = v_from_x_coord_y_inverted(pixmap, y1); - vertices[2][1] = v_from_x_coord_y_inverted(pixmap, y2); - vertices[3][1] = v_from_x_coord_y_inverted(pixmap, y2); + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, + x1, y1,x2, y2, + glamor_priv->yInverted, + vertices); - source_texcoords[0][1] = t_from_x_coord_y_inverted(tile, tile_y1); - source_texcoords[1][1] = t_from_x_coord_y_inverted(tile, tile_y1); - source_texcoords[2][1] = t_from_x_coord_y_inverted(tile, tile_y2); - source_texcoords[3][1] = t_from_x_coord_y_inverted(tile, tile_y2); - } else { + glamor_set_normalize_tcoords(src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); - vertices[0][1] = v_from_x_coord_y(pixmap, y1); - vertices[1][1] = v_from_x_coord_y(pixmap, y1); - vertices[2][1] = v_from_x_coord_y(pixmap, y2); - vertices[3][1] = v_from_x_coord_y(pixmap, y2); - - source_texcoords[0][1] = t_from_x_coord_y(tile, tile_y1); - source_texcoords[1][1] = t_from_x_coord_y(tile, tile_y1); - source_texcoords[2][1] = t_from_x_coord_y(tile, tile_y2); - source_texcoords[3][1] = t_from_x_coord_y(tile, tile_y2); - } glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h new file mode 100644 index 000000000..b8b437eb8 --- /dev/null +++ b/glamor/glamor_utils.h @@ -0,0 +1,124 @@ +#ifndef GLAMOR_PRIV_H +#error This file can only be included by glamor_priv.h +#endif + +#ifndef __GLAMOR_UTILS_H__ +#define __GLAMOR_UTILS_H__ + +#define v_from_x_coord_x(_xscale_, _x_) ( 2 * (_x_) * (_xscale_) - 1.0) +#define v_from_x_coord_y(_yscale_, _y_) (-2 * (_y_) * (_yscale_) + 1.0) +#define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0) +#define t_from_x_coord_x(_xscale_, _x_) ((_x_) * (_xscale_)) +#define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_)) +#define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) + +#define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ + do { \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height; \ + } while(0) + + +#define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \ + + ((float)xFixedFrac(_val_) / 65536.0)) + +#define glamor_picture_get_matrixf(_picture_, _matrix_) \ + do { \ + int _i_; \ + if ((_picture_)->transform) \ + { \ + for(_i_ = 0; _i_ < 3; _i_++) \ + { \ + (_matrix_)[_i_ * 3 + 0] = \ + xFixedToFloat((_picture_)->transform->matrix[_i_][0]); \ + (_matrix_)[_i_ * 3 + 1] = \ + xFixedToFloat((_picture_)->transform->matrix[_i_][1]); \ + (_matrix_)[_i_ * 3 + 2] = \ + xFixedToFloat((_picture_)->transform->matrix[_i_][2]); \ + } \ + } \ + } while(0) + +#define glamor_set_transformed_point(matrix, xscale, yscale, texcoord, \ + x, y, yInverted) \ + do { \ + float result[4]; \ + int i; \ + float tx, ty; \ + \ + for (i = 0; i < 3; i++) { \ + result[i] = (matrix)[i * 3] * (x) + (matrix)[i * 3 + 1] * (y) \ + + (matrix)[i * 3 + 2]; \ + } \ + tx = result[0] / result[2]; \ + ty = result[1] / result[2]; \ + \ + (texcoord)[0] = t_from_x_coord_x(xscale, tx); \ + if (yInverted) \ + (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \ + else \ + (texcoord)[1] = t_from_x_coord_y(yscale, ty); \ + } while(0) + + +#define glamor_set_transformed_normalize_tcoords( matrix, \ + xscale, \ + yscale, \ + tx1, ty1, tx2, ty2, \ + yInverted, texcoords) \ + do { \ + glamor_set_transformed_point(matrix, xscale, yscale, \ + texcoords, tx1, ty1, \ + yInverted); \ + glamor_set_transformed_point(matrix, xscale, yscale, \ + texcoords + 2, tx2, ty1, \ + yInverted); \ + glamor_set_transformed_point(matrix, xscale, yscale, \ + texcoords + 4, tx2, ty2, \ + yInverted); \ + glamor_set_transformed_point(matrix, xscale, yscale, \ + texcoords + 6, tx1, ty2, \ + yInverted); \ + } while (0) + +#define glamor_set_normalize_tcoords(xscale, yscale, x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = t_from_x_coord_x(xscale, x1); \ + (vertices)[2] = t_from_x_coord_x(xscale, x2); \ + (vertices)[4] = (vertices)[2]; \ + (vertices)[6] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \ + (vertices)[5] = t_from_x_coord_y_inverted(yscale, y2); \ + } \ + else { \ + (vertices)[1] = t_from_x_coord_y(yscale, y1); \ + (vertices)[5] = t_from_x_coord_y(yscale, y2); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[7] = (vertices)[5]; \ + } while(0) + + +#define glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = v_from_x_coord_x(xscale, x1); \ + (vertices)[2] = v_from_x_coord_x(xscale, x2); \ + (vertices)[4] = (vertices)[2]; \ + (vertices)[6] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ + (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2); \ + } \ + else { \ + (vertices)[1] = v_from_x_coord_y(yscale, y1); \ + (vertices)[5] = v_from_x_coord_y(yscale, y2); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[7] = (vertices)[5]; \ + } while(0) + + +#endif From ca36ada041558d1823b12b1a0141e43b9f9ad939 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 22 Jun 2011 18:15:02 +0800 Subject: [PATCH 135/462] glamor: Don't always fallback everything when change window attr. Change the glamor_change_window_attributes's handling. We don't need to fallback every thing to cpu at the beginning. Only when there is a real need to change the pixmap's format, we need to do something. Otherwise, we need do nothing here. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor_core.c | 52 +++++------------------------ glamor/glamor_debug.h | 19 +++++++++-- glamor/glamor_render.c | 18 ++++++++-- glamor/glamor_tile.c | 5 ++- glamor/glamor_window.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 51 deletions(-) create mode 100644 glamor/glamor_window.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 53877dcbe..e2678f060 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -33,6 +33,7 @@ libglamor_la_SOURCES = \ glamor_triangles.c\ glamor_pixmap.c\ glamor_picture.c\ + glamor_window.c\ glamor.h libglamor_la_LIBADD = \ glu3/libglu3.la diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index a61b8ae53..31734bed0 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -241,10 +241,13 @@ glamor_finish_access(DrawablePtr drawable) Bool glamor_prepare_access_gc(GCPtr gc) { - if (gc->stipple) + if (gc->stipple) { + glamor_fallback("has stipple %p\n", gc->stipple); if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO)) return FALSE; + } if (gc->fillStyle == FillTiled) { + glamor_fallback("has tile pixmap %p\n", gc->tile.pixmap); if (!glamor_prepare_access (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RO)) { if (gc->stipple) @@ -332,6 +335,8 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) /* fb24_32ReformatTile will do direct access of a newly- * allocated pixmap. */ + glamor_fallback("GC %p tile FB_24_32 transformat %p.\n", gc, old_tile); + if (glamor_prepare_access(&old_tile->drawable, GLAMOR_ACCESS_RO)) { new_tile = fb24_32ReformatTile(old_tile, @@ -351,6 +356,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) if (!gc->tileIsPixel && FbEvenTile(gc->tile.pixmap->drawable.width * drawable->bitsPerPixel)) { + glamor_fallback("GC %p tile changed %p.\n", gc, gc->tile.pixmap); if (glamor_prepare_access(&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW)) { fbPadPixmap(gc->tile.pixmap); @@ -367,6 +373,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) /* We can't inline stipple handling like we do for GCTile because * it sets fbgc privates. */ + glamor_fallback("GC %p stipple changed %p.\n", gc, gc->stipple); if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { fbValidateGC(gc, changes, drawable); glamor_finish_access(&gc->stipple->drawable); @@ -403,52 +410,11 @@ glamor_create_gc(GCPtr gc) 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->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; -} - -void -glamor_finish_access_window(WindowPtr window) -{ - if (window->backgroundState == BackgroundPixmap) - glamor_finish_access(&window->background.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; - - if (!glamor_prepare_access_window(window)) - return FALSE; - ret = fbChangeWindowAttributes(window, mask); - glamor_finish_access_window(window); - return ret; -} - RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap) { RegionPtr ret; + glamor_fallback("pixmap %p \n", pixmap); if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) return NULL; ret = fbPixmapToRegion(pixmap); diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h index aad4b3ca6..48682e802 100644 --- a/glamor/glamor_debug.h +++ b/glamor/glamor_debug.h @@ -5,9 +5,24 @@ #define GLAMOR_DELAYED_STRING_MAX 64 #define GLAMOR_DEBUG_NONE 0 +#define GLAMOR_DEBUG_UNIMPL 0 #define GLAMOR_DEBUG_FALLBACK 1 -#define GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD 2 -#define GLAMOR_DEBUG_TEXTURE_DOWNLOAD 3 +#define GLAMOR_DEBUG_TEXTURE_DOWNLOAD 2 +#define GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD 3 + +extern void +AbortServer(void) _X_NORETURN; + +#define GLAMOR_PANIC(_format_, ...) \ + do { \ + LogMessageVerb(X_NONE, 0, "Glamor Fatal Error" \ + " at %32s line %d: " _format_ "\n", \ + __FUNCTION__, __LINE__, \ + ##__VA_ARGS__ ); \ + AbortServer(); \ + } while(0) + + #define __debug_output_message(_format_, _prefix_, ...) \ diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f991b0f17..14c3fa8d8 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -748,6 +748,7 @@ glamor_composite_with_shader(CARD8 op, if (source->pSourcePict->type == SourcePictTypeSolidFill) { key.source = SHADER_SOURCE_SOLID; } else { + //key.source = SHADER_SOURCE_SOLID; glamor_fallback("gradient source\n"); goto fail; } @@ -1134,12 +1135,23 @@ glamor_composite(CARD8 op, return; fail: - glamor_fallback("glamor_composite(): " - "from picts %p/%p(%c,%c) to pict %p (%c)\n", - source, mask, + + glamor_fallback( + "from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", + source, + source->pDrawable, + source->pDrawable ? source->pDrawable->width : 0, + source->pDrawable ? source->pDrawable->height : 0, + mask, + (!mask) ? NULL : mask->pDrawable, + (!mask || !mask->pDrawable)? 0 : mask->pDrawable->width, + (!mask || !mask->pDrawable)? 0 : mask->pDrawable->height, glamor_get_picture_location(source), glamor_get_picture_location(mask), dest, + dest->pDrawable, + dest->pDrawable->width, + dest->pDrawable->height, glamor_get_picture_location(dest)); glUseProgramObjectARB(0); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 90bf734be..c62392c1b 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -94,18 +94,17 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; + src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); - if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; } - if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest has no fbo."); + glamor_fallback("dest has no fbo.\n"); goto fail; } diff --git a/glamor/glamor_window.c b/glamor/glamor_window.c new file mode 100644 index 000000000..05555b204 --- /dev/null +++ b/glamor/glamor_window.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2008 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +/** @file glamor_window.c + * + * Screen Change Window Attribute implementation. + */ + + +static void +glamor_fixup_window_pixmap(DrawablePtr pDrawable, PixmapPtr *ppPixmap) +{ + PixmapPtr pPixmap = *ppPixmap; + glamor_pixmap_private *pixmap_priv; + + if (pPixmap->drawable.bitsPerPixel != pDrawable->bitsPerPixel) + { + pixmap_priv = glamor_get_pixmap_private(pPixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("pixmap %p has no fbo\n", pPixmap); + goto fail; + } + glamor_debug_output(GLAMOR_DEBUG_UNIMPL, "To be implemented.\n"); + } + return; + +fail: + GLAMOR_PANIC(" We can't fall back to fbFixupWindowPixmap, as the fb24_32ReformatTile" + " is broken for glamor. \n"); +} + +Bool +glamor_change_window_attributes(WindowPtr pWin, unsigned long mask) +{ + if (mask & CWBackPixmap) { + if (pWin->backgroundState == BackgroundPixmap) + glamor_fixup_window_pixmap(&pWin->drawable, &pWin->background.pixmap); + } + + if (mask & CWBorderPixmap) { + if (pWin->borderIsPixel == FALSE) + glamor_fixup_window_pixmap(&pWin->drawable, &pWin->border.pixmap); + } + return TRUE; +} + + + From 489e6c4e6f734d961ae8bbec67d78fccbeb9781f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 26 Jun 2011 15:49:13 +0800 Subject: [PATCH 136/462] glamor: Initialize pixmap private's container to correct value. When calling from ephyr, we forgot to initialize it to the correct value. Will cause segfault when run Xephyr. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index c10ff4021..54304226e 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -197,6 +197,7 @@ glamor_create_screen_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->tex = 0; pixmap_priv->gl_fbo = 1; pixmap_priv->gl_tex = 1; + pixmap_priv->container = pixmap; screen->CreatePixmap = glamor_create_pixmap; return pixmap; From bf782283371bc13c7b969a373c2a2eaaa3c81ec6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 26 Jun 2011 15:51:47 +0800 Subject: [PATCH 137/462] glamor: Fixed one bug when enable dynamic pixmap uploading. When try to upload a pixmap without yInverted set, we must set up a fbo for it to do the y flip. Previous implementation only consider the ax bit. After fix this problem, we can enable the dynamic uploading feature in copyarea function when the yInverted is not set (from Xephyr). Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 2 -- glamor/glamor_pixmap.c | 35 +++++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 55437715a..b1d8cfcea 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -224,8 +224,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, 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; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 6e2d9d576..b532bb394 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -241,11 +241,19 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i } -/* */ +/* + * Prepare to upload a pixmap to texture memory. + * ax 1 means the format needs to wire alpha to 1. + * Two condtion need to setup a fbo for a pixmap + * 1. !yInverted, we need to do flip if we are not yInverted. + * 2. ax != 0, we need to wire the alpha. + * */ static int -glamor_pixmap_upload_prepare(PixmapPtr pixmap, int need_fbo) +glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) { + int need_fbo; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); if (!glamor_check_fbo_width_height(pixmap->drawable.width , pixmap->drawable.height) || !glamor_check_fbo_depth(pixmap->drawable.depth)) { @@ -253,25 +261,28 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int need_fbo) 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. - */ + + if (ax != 0 || !glamor_priv->yInverted) + need_fbo = 1; + else + need_fbo = 0; + + if (pixmap_priv->tex == 0) glGenTextures(1, &pixmap_priv->tex); + + if (need_fbo) { + if (pixmap_priv->fb == 0) + glGenFramebuffersEXT(1, &pixmap_priv->fb); 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, @@ -304,7 +315,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth); - _glamor_upload_pixmap_to_texture(pixmap, format, type, ax, 0); + _glamor_upload_pixmap_to_texture(pixmap, format, type, ax, 1); return GLAMOR_UPLOAD_DONE; } From b8e692d94eb7075409e0d072fdf3066ca1d5d5f3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 26 Jun 2011 15:54:24 +0800 Subject: [PATCH 138/462] glamor: Move the blend set up after the pixmap uploading. This is a bug, as if we do blend set up before do the pixmap dynamic uploading. We will have a incorrect blend env when doing the uploading. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 14c3fa8d8..2d89cd48d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -734,7 +734,7 @@ glamor_composite_with_shader(CARD8 op, 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; + PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); @@ -838,10 +838,6 @@ glamor_composite_with_shader(CARD8 op, 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 @@ -849,17 +845,13 @@ glamor_composite_with_shader(CARD8 op, 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); } @@ -913,7 +905,9 @@ glamor_composite_with_shader(CARD8 op, } } #endif - + if (!glamor_set_composite_op(screen, op, dest, mask)) { + goto fail; + } glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); shader = glamor_lookup_composite_shader(screen, &key); From cbedfe75135e3253c32ac8b89380f47d1b8a37c4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 26 Jun 2011 20:00:26 +0800 Subject: [PATCH 139/462] glamor: Don't need to read dest if op is SRC or CLEAR. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 2d89cd48d..59a74dfb3 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1084,6 +1084,7 @@ glamor_composite(CARD8 op, CARD16 height) { glamor_composite_rect_t rect; + glamor_access_t dest_access; /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. @@ -1150,7 +1151,11 @@ glamor_composite(CARD8 op, glUseProgramObjectARB(0); glDisable(GL_BLEND); - if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { + if (op == PictOpSrc || op == PictOpClear) + dest_access = GLAMOR_ACCESS_WO; + else + dest_access = GLAMOR_ACCESS_RW; + if (glamor_prepare_access_picture(dest, dest_access)) { if (glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO)) { if (!mask || From 4afa9e4080eebbee0752e5f45b2ff16df75cb9b1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 28 Jun 2011 14:28:19 +0800 Subject: [PATCH 140/462] glamor: Prepare/finish access once if src equal to dst. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index b1d8cfcea..cebce218b 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -322,6 +322,7 @@ glamor_copy_n_to_n(DrawablePtr src, goto done; return; } + glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); @@ -329,11 +330,12 @@ glamor_copy_n_to_n(DrawablePtr src, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { - if (glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { + if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); - glamor_finish_access(src); + if (dst != src) + glamor_finish_access(src); } glamor_finish_access(dst); } From 9e4567afe6019ed7a330182d660880d8ea6c3685 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 28 Jun 2011 14:37:29 +0800 Subject: [PATCH 141/462] glamor: Change to use system memory for write only access. If the pixmap is write-only, then use a pbo mapping will not get too much benefit. And even worse, when the software rendering is access this mapped data range, it's much slower than just using a system memory. From the glamor_prepare_access glamor_finish_access view, we have two options here: option 1: 1.0 create a pbo 1.1 copy texture to the pbo 1.2 map the pbo to va 1.3 access the va directly in software rendering. 1.4 bind the pbo as unpack buffer & draw it back to texture. option 2: 2.0 allocate a block memory in system memory space. 2.1 read the texture memory to the system memory. 2.2 access the system memory and do rendering. 2.3 draw the system memory back to texture. In general, 1.1 plush 1.2 is much faster than 2.1. And 1.3 is slower than 2.2. 1.4 is faster than 2.3. If the access mode is read only or read write, option 1 may be fater, but if the access mode is write only. Then most of the time option 1 is much faster. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index b532bb394..c76920a26 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -387,15 +387,23 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } pixmap_priv->access_mode = access; - + 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; + 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; + data = malloc(stride * pixmap->drawable.height); + goto done; break; case GLAMOR_ACCESS_RW: gl_access = GL_READ_WRITE_ARB; @@ -405,15 +413,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) 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); @@ -429,8 +429,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glBufferDataARB (GL_PIXEL_PACK_BUFFER_EXT, stride * pixmap->drawable.height, NULL, gl_usage); - if (access != GLAMOR_ACCESS_WO) - glReadPixels (0, 0, + glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); data = glMapBufferARB (GL_PIXEL_PACK_BUFFER_EXT, gl_access); @@ -438,7 +437,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (!glamor_priv->yInverted) glPixelStorei(GL_PACK_INVERT_MESA, 0); - + glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); } else { data = malloc(stride * pixmap->drawable.height); assert(data); @@ -465,6 +464,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +done: pixmap->devPrivate.ptr = data; return TRUE; } From c303949aabacb6a105ca0e0c521ca293dbda7d43 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 28 Jun 2011 14:49:38 +0800 Subject: [PATCH 142/462] glamor: Reduce one extra copy in glamor_trapezoids. This reduce the time when running cairo-performance-trace with the firefox-planet-gnome.trace from 23.5 seconds to 21.5 seconds. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 43 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 59a74dfb3..27fff23b2 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -748,7 +748,6 @@ glamor_composite_with_shader(CARD8 op, if (source->pSourcePict->type == SourcePictTypeSolidFill) { key.source = SHADER_SOURCE_SOLID; } else { - //key.source = SHADER_SOURCE_SOLID; glamor_fallback("gradient source\n"); goto fail; } @@ -1201,7 +1200,7 @@ glamor_create_mask_picture(ScreenPtr screen, return 0; } - pixmap = screen->CreatePixmap(screen, width, height, + pixmap = screen->CreatePixmap(screen, 0, 0, pict_format->depth, 0); if (!pixmap) @@ -1229,7 +1228,6 @@ glamor_trapezoids(CARD8 op, 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 @@ -1256,8 +1254,7 @@ glamor_trapezoids(CARD8 op, width = bounds.x2 - bounds.x1; height = bounds.y2 - bounds.y1; - stride = (width * BitsPerPixel(mask_format->depth) + 7) / 8; - + stride = PixmapBytePad(width, mask_format->depth); picture = glamor_create_mask_picture(screen, dst, mask_format, width, height); if (!picture) @@ -1275,32 +1272,13 @@ glamor_trapezoids(CARD8 op, 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); + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + + screen->ModifyPixmapHeader(pixmap, width, height, + mask_format->depth, + BitsPerPixel(mask_format->depth), + PixmapBytePad(width, mask_format->depth), + pixman_image_get_data(image)); x_rel = bounds.x1 + x_src - x_dst; y_rel = bounds.y1 + y_src - y_dst; @@ -1309,6 +1287,9 @@ glamor_trapezoids(CARD8 op, 0, 0, bounds.x1, bounds.y1, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + + pixman_image_unref(image); + FreePicture(picture, 0); } From 8890b38857128181cf506356046bf4a5bce53ab0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 28 Jun 2011 17:17:23 +0800 Subject: [PATCH 143/462] glamor: Don't map the vbo to system memory. Access mapped vbo address is too slow. And by use system memory directly, rgb10text/aa10text increases from 980K/1160K to 117K/140K. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 ++ glamor/glamor_render.c | 31 +++++++++++++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 54304226e..b78feb4ec 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -399,6 +399,8 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->CreatePicture = glamor_priv->saved_create_picture; } #endif + if (glamor_priv->vb) + free(glamor_priv->vb); free(glamor_priv); return screen->CloseScreen(idx, screen); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 27fff23b2..e7a886c4b 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -285,10 +285,25 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) return shader; } +#define GLAMOR_COMPOSITE_VBO_SIZE 8192 + +static void +glamor_reset_composite_vbo(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_priv->vbo_offset = 0; + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_SIZE; + glamor_priv->render_nr_verts = 0; +} + void glamor_init_composite_shaders(ScreenPtr screen) { + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_priv->vb = malloc(GLAMOR_COMPOSITE_VBO_SIZE); + assert(glamor_priv->vb != NULL); + glamor_reset_composite_vbo(screen); } static Bool @@ -599,13 +614,11 @@ glamor_flush_composite_rects(ScreenPtr screen) if (!glamor_priv->render_nr_verts) return; - - glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); - glamor_priv->vb = NULL; + glBufferDataARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo_offset, glamor_priv->vb, + GL_STREAM_DRAW_ARB); glDrawArrays(GL_QUADS, 0, glamor_priv->render_nr_verts); - glamor_priv->render_nr_verts = 0; - glamor_priv->vbo_size = 0; + glamor_reset_composite_vbo(screen); } static void @@ -622,16 +635,10 @@ glamor_emit_composite_rect(ScreenPtr screen, glamor_flush_composite_rects(screen); } - if (glamor_priv->vbo_size == 0) { + if (glamor_priv->vbo_offset == 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); } From 33c6c78ae9c7e72a94cc27536f3b5f50cdcc9241 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:01:57 +0800 Subject: [PATCH 144/462] glamor: Add one option to force create a cpu memory pixmap. Some special case we want to get a cpu memory pixmap. For example to gather a large cpu memory pixmap's block to a small pixmap. Add pixmap's priviate data's deallocation when destroy a pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 12 +++++++----- glamor/glamor_priv.h | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index b78feb4ec..6bab8c124 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -116,11 +116,12 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, GLuint tex; int type = GLAMOR_PIXMAP_TEXTURE; glamor_pixmap_private *pixmap_priv; - if (w > 32767 || h > 32767) return NullPixmap; - if (!glamor_check_fbo_width_height(w,h) || !glamor_check_fbo_depth(depth)) { + if (!glamor_check_fbo_width_height(w,h) + || !glamor_check_fbo_depth(depth) + || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. If we exceed such limitation, we have to use framebuffer.*/ type = GLAMOR_PIXMAP_MEMORY; @@ -129,9 +130,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, NULL); - - glamor_fallback("choose cpu memory for pixmap %p ," - " %d x %d depth %d\n", pixmap, w, h, depth); + if (usage != GLAMOR_CREATE_PIXMAP_CPU) + 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); @@ -217,6 +218,7 @@ glamor_destroy_pixmap(PixmapPtr pixmap) glDeleteTextures(1, &pixmap_priv->tex); if (pixmap_priv->pbo) glDeleteBuffersARB(1, &pixmap_priv->pbo); + dixFreePrivates(pixmap->devPrivates, PRIVATE_PIXMAP); } return fbDestroyPixmap(pixmap); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 5b457e7fc..4b0037333 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -50,9 +50,9 @@ #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_width_height(_w_, _h_) ((_w_) > 0 && (_h_) > 0 \ + && (_w_) < MAX_WIDTH \ + && (_h_) < MAX_HEIGHT) #define glamor_check_fbo_depth(_depth_) ( \ _depth_ == 8 \ @@ -149,6 +149,7 @@ enum shader_in { SHADER_IN_COUNT, }; +#define GLAMOR_CREATE_PIXMAP_CPU 0x100 typedef struct glamor_screen_private { CloseScreenProcPtr saved_close_screen; CreateGCProcPtr saved_create_gc; From 1dca5d7b91ed6fced34f389453678407bc223e9c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:04:59 +0800 Subject: [PATCH 145/462] glamor: Reduce source pixmap's size. If the dest pixmap is in texture memory, but source pixmap is not. Then we need to upload the source pixmap to texture memory. Previous version will upload the whole source pixmap. This commit preprocess the source pixmap, and reduce it to a smaller tempory pixmap only contains the required region. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 60 +++++++++++++++++++++++++++++++++++++--- glamor/glamor_utils.h | 38 +++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index cebce218b..2408e3aae 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -308,6 +308,23 @@ glamor_copy_n_to_n(DrawablePtr src, Pixel bitplane, void *closure) { + glamor_access_t dst_access; + PixmapPtr dst_pixmap, src_pixmap, temp_pixmap; + DrawablePtr temp_src = src; + glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; + BoxRec bound; + ScreenPtr screen; + int temp_dx = dx; + int temp_dy = dy; + dst_pixmap = glamor_get_drawable_pixmap(dst); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + screen = dst_pixmap->drawable.pScreen; + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); + goto fail; + } + if (glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { goto done; return; @@ -318,17 +335,50 @@ glamor_copy_n_to_n(DrawablePtr src, return; } - if (glamor_copy_n_to_n_textured(src, dst, gc, box, nbox, dx, dy)) { - goto done; - return; + src_pixmap = glamor_get_drawable_pixmap(src); + src_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + + glamor_calculate_boxes_bound(&bound, box, nbox); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) + && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) + * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height)) { + + temp_pixmap = (*screen->CreatePixmap)(screen, + bound.x2 - bound.x1, + bound.y2 - bound.y1, + src_pixmap->drawable.depth, + GLAMOR_CREATE_PIXMAP_CPU); + if (!temp_src) + goto fail; + glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + fbCopyNtoN(src, temp_src, gc, box, nbox, + temp_dx + bound.x1, temp_dy + bound.y1, + reverse, upsidedown, bitplane, + closure); + glamor_transform_boxes(box, nbox, bound.x1, bound.y1); + temp_dx = -bound.x1; + temp_dy = -bound.y1; + temp_src = &temp_pixmap->drawable; } + if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { + goto done; + } + + fail: glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); glamor_fallback("from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); + + if (gc && gc->alu != GXcopy) + dst_access = GLAMOR_ACCESS_RW; + else + dst_access = GLAMOR_ACCESS_WO; + if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { fbCopyNtoN(src, dst, gc, box, nbox, @@ -339,11 +389,13 @@ 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); + if (temp_src != src) { + (*screen->DestroyPixmap)(temp_pixmap); + } } RegionPtr diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index b8b437eb8..2c6563232 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -121,4 +121,42 @@ } while(0) +inline static void +glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) +{ + int x_min, y_min; + int x_max, y_max; + int i; + x_min = y_min = MAXSHORT; + x_max = y_max = MINSHORT; + for(i = 0; i < nbox; i++) + { + if (x_min > boxes[i].x1) + x_min = boxes[i].x1; + if (y_min > boxes[i].y1) + x_min = boxes[i].y1; + + if (x_max < boxes[i].x2) + x_max = boxes[i].x2; + if (y_max > boxes[i].y2) + y_max = boxes[i].y2; + } + bound->x1 = x_min; + bound->y1 = y_min; + bound->x2 = x_max; + bound->y2 = y_max; +} + +inline static void +glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) +{ + int i; + for (i = 0; i < nbox; i++) + { + boxes[i].x1 += dx; + boxes[i].y1 += dy; + boxes[i].x2 += dx; + boxes[i].y2 += dy; + } +} #endif From 14503fbb819d07fa2b58d9bb741b55f93aff2cf6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:38:43 +0800 Subject: [PATCH 146/462] glamor: Fix the coords calculation in glamor_fill. glamor_fill is only called from internal functions glamor_fillspancs and glamor_polyfillrect. And both functions already add the offset to the coords, so the coords are already relative value, we can't add the offset once again. Signed-off-by: Zhigang Gong --- glamor/glamor_fill.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 48f85ce38..a41837b3a 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -41,14 +41,12 @@ glamor_fill(DrawablePtr drawable, int height) { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); - int x_off, y_off; - glamor_get_drawable_deltas(drawable, dst_pixmap, &x_off, &y_off); switch (gc->fillStyle) { case FillSolid: if (!glamor_solid(dst_pixmap, - x + x_off, - y + y_off, + x, + y, width, height, gc->alu, @@ -60,24 +58,24 @@ glamor_fill(DrawablePtr drawable, case FillOpaqueStippled: if (!glamor_stipple(dst_pixmap, gc->stipple, - x+ x_off, - y + y_off, + x, + y, width, height, gc->alu, gc->planemask, gc->fgPixel, gc->bgPixel, - gc->patOrg.x + x_off, - gc->patOrg.y + y_off)) + gc->patOrg.x, + gc->patOrg.y)) goto fail; return; break; case FillTiled: if (!glamor_tile(dst_pixmap, gc->tile.pixmap, - x + x_off, - y + y_off, + x, + y, width, height, gc->alu, From 61e1ad39724e5baaed4f30ff3c86782e701f19fb Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:40:32 +0800 Subject: [PATCH 147/462] glamor: Reduce source or mask picture size if possible. If we only need a short part of the source or mask's drawable pixmap, we can convert it to a new small picture before call to the low level compositing function. Then it will only upload the smaller picture latter. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 144 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 127 insertions(+), 17 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e7a886c4b..1c4c1b366 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1075,6 +1075,53 @@ glamor_composite_with_shader(CARD8 op, return FALSE; } +static PicturePtr +glamor_convert_gradient_picture(ScreenPtr screen, + PicturePtr source, + int x_source, + int y_source, + int width, + int height) +{ + PixmapPtr pixmap; + PicturePtr dst; + int error; + PictFormatShort format; + + if (!source->pDrawable) + format = PICT_a8r8g8b8; + else + format = source->format; + + pixmap = screen->CreatePixmap(screen, + width, + height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_CPU); + + if (!pixmap) + return NULL; + + dst = CreatePicture(0, + &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, + 0, + serverClient, + &error); + screen->DestroyPixmap(pixmap); + if (!dst) + return NULL; + + ValidatePicture(dst); + + fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, + 0, 0, 0, 0, width, height); + return dst; +} + void glamor_composite(CARD8 op, PicturePtr source, @@ -1089,27 +1136,84 @@ glamor_composite(CARD8 op, CARD16 width, CARD16 height) { + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_pixmap_private *dest_pixmap_priv, *source_pixmap_priv, *mask_pixmap_priv; + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap, mask_pixmap; + PicturePtr temp_src = source, temp_mask = mask; + int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; glamor_composite_rect_t rect; glamor_access_t dest_access; + x_temp_src = x_source; + y_temp_src = y_source; + x_temp_mask = x_mask; + y_temp_mask = y_mask; + + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + /* Currently. Always fallback to cpu if destination is in CPU memory. */ + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + goto fail; + } + + if (source->pDrawable) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + } + + if (mask && mask->pDrawable) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + } + + if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) + || (source->pDrawable + && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) + && (width * height * 4 + < (source_pixmap->drawable.width * source_pixmap->drawable.height)))){ + temp_src = glamor_convert_gradient_picture(screen, source, x_source, y_source, width, height); + if (!temp_src) { + temp_src = source; + goto fail; + } + x_temp_src = y_temp_src = 0; + } + + if (mask + && ((!mask->pDrawable && (mask->pSourcePict->type != SourcePictTypeSolidFill)) + || (mask->pDrawable + && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) + && (width * height * 4 + < (mask_pixmap->drawable.width * mask_pixmap->drawable.height))))) { + /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity + * to do reduce one convertion. */ + temp_mask = glamor_convert_gradient_picture(screen, mask, x_mask, y_mask, width, height); + if (!temp_mask) { + temp_mask = mask; + goto fail; + } + x_temp_mask = y_temp_mask = 0; + } /* 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, + temp_src, temp_mask, dest, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, x_dest, y_dest, width, height); glamor_composite(PictOpAdd, - source, mask, dest, - x_source, y_source, - x_mask, y_mask, + temp_src, temp_mask, dest, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, x_dest, y_dest, width, height); - return; + goto done; + } else if (op != PictOpAdd && op != PictOpOutReverse) { glamor_fallback("glamor_composite(): component alpha\n"); goto fail; @@ -1117,25 +1221,25 @@ glamor_composite(CARD8 op, } if (!mask) { - if (glamor_composite_with_copy(op, source, dest, - x_source, y_source, + if (glamor_composite_with_copy(op, temp_src, dest, + x_temp_src, y_temp_src, x_dest, y_dest, width, height)) - return; + goto done; } - rect.x_src = x_source; - rect.y_src = y_source; - rect.x_mask = x_mask; - rect.y_mask = y_mask; + rect.x_src = x_temp_src; + rect.y_src = y_temp_src; + rect.x_mask = x_temp_mask; + rect.y_mask = y_temp_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; + if (glamor_composite_with_shader(op, temp_src, temp_mask, dest, 1, &rect)) + goto done; - fail: +fail: glamor_fallback( "from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", @@ -1157,6 +1261,7 @@ glamor_composite(CARD8 op, glUseProgramObjectARB(0); glDisable(GL_BLEND); + if (op == PictOpSrc || op == PictOpClear) dest_access = GLAMOR_ACCESS_WO; else @@ -1180,6 +1285,11 @@ glamor_composite(CARD8 op, } glamor_finish_access_picture(dest); } +done: + if (temp_src != source) + FreePicture(temp_src, 0); + if (temp_mask != mask) + FreePicture(temp_mask, 0); } From 2eb40a37920132d53e3b48830704f92d4c695f4c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:49:40 +0800 Subject: [PATCH 148/462] glamor: Remove one extra area copy in glamor_glyph. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 26e08470a..63ffd205c 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -375,6 +375,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, ValidateGC(&cache_pixmap->drawable, gc); /* Create a temporary bo to stream the updates to the cache */ +#if 0 scratch = screen->CreatePixmap(screen, glyph->info.width, glyph->info.height, @@ -390,7 +391,8 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, } else { scratch = glyph_pixmap; } - +#endif + scratch = glyph_pixmap; (void)glamor_copy_area(&scratch->drawable, &cache_pixmap->drawable, gc, From 734b10e9f7e729fc300ed432bd3c81e1ea7483f3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:50:23 +0800 Subject: [PATCH 149/462] glamor: Fix one typo bug in glamor_tile. It will return when the destination pixmap has a fbo but will continue when it doesn't have a fbo. Signed-off-by: Zhigang Gong --- glamor/glamor_tile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index c62392c1b..5bfdd7341 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -103,7 +103,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, goto fail; } - if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; } From 1444fed4a8030ec59f4448b490f2f77db86f0b86 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:53:24 +0800 Subject: [PATCH 150/462] glamor: silence compilation warnings. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 1c4c1b366..9599d978a 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1137,9 +1137,10 @@ glamor_composite(CARD8 op, CARD16 height) { ScreenPtr screen = dest->pDrawable->pScreen; - glamor_pixmap_private *dest_pixmap_priv, *source_pixmap_priv, *mask_pixmap_priv; + glamor_pixmap_private *dest_pixmap_priv; + glamor_pixmap_private *source_pixmap_priv = NULL, *mask_pixmap_priv = NULL; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); - PixmapPtr source_pixmap, mask_pixmap; + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; PicturePtr temp_src = source, temp_mask = mask; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; glamor_composite_rect_t rect; From ca614860fa2a56d469064b5e05070d8201597728 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 1 Jul 2011 17:02:10 +0800 Subject: [PATCH 151/462] glamor: convert if too large source or mask . Some strange web page has 20000*1 png picture, and actually only use partial of it. We force to convert it to a actuall size rather than its original size,if it is the case. Then to avoid latter's failure uploading. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 9599d978a..72e0f83c6 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1170,8 +1170,10 @@ glamor_composite(CARD8 op, if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) - && (width * height * 4 - < (source_pixmap->drawable.width * source_pixmap->drawable.height)))){ + && ((width * height * 4 + < (source_pixmap->drawable.width * source_pixmap->drawable.height)) + || !(glamor_check_fbo_width_height(source_pixmap->drawable.width, + source_pixmap->drawable.height))))) { temp_src = glamor_convert_gradient_picture(screen, source, x_source, y_source, width, height); if (!temp_src) { temp_src = source; @@ -1184,8 +1186,10 @@ glamor_composite(CARD8 op, && ((!mask->pDrawable && (mask->pSourcePict->type != SourcePictTypeSolidFill)) || (mask->pDrawable && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) - && (width * height * 4 - < (mask_pixmap->drawable.width * mask_pixmap->drawable.height))))) { + && ((width * height * 4 + < (mask_pixmap->drawable.width * mask_pixmap->drawable.height)) + || !(glamor_check_fbo_width_height(mask_pixmap->drawable.width, + mask_pixmap->drawable.height)))))) { /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity * to do reduce one convertion. */ temp_mask = glamor_convert_gradient_picture(screen, mask, x_mask, y_mask, width, height); From c68fb6ed723d7268a3c4950b40c20ddf9b4b9ca5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 1 Jul 2011 22:36:31 +0800 Subject: [PATCH 152/462] glamor-ddx: Reinit crtc if we need to reopen the card. As the eglTerminate will close the card when close screen, we may need to reopen it at next time create a screen resource. and thus we need to re initialize the drmmode crtc also. Otherwise , the cursor handling will be broken as it has the wrong fd. --- hw/xfree86/glamor/glamor.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index d0432b31e..1da7eb20d 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -145,6 +145,12 @@ EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) return eglCreateDRMImageMESA(glamor->display, attribs); } +void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor) +{ + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + eglDestroyImageKHR(glamor->display, cursor); +} + void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uint32_t *pitch) { @@ -191,7 +197,7 @@ glamor_pre_init_ddx(ScrnInfoPtr scrn, int flags) if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); - goto fail; + goto fail; } scrn->currentMode = scrn->modes; @@ -272,6 +278,8 @@ glamor_close_screen_ddx(int scrnIndex, ScreenPtr screen) glamor_fini(screen); + eglDestroyImageKHR(glamor->display, glamor->root); + eglMakeCurrent(glamor->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(glamor->display); @@ -279,6 +287,7 @@ glamor_close_screen_ddx(int scrnIndex, ScreenPtr screen) drmmode_closefb(scrn); glamor->fd = -1; + glamor->root = EGL_NO_IMAGE_KHR; return TRUE; @@ -301,8 +310,16 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) ErrorF("Failed to open %s: %s\n", dri_device_name, strerror(errno)); return FALSE; } + if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Kernel modesetting setup failed\n"); + return FALSE; } + } + + + glamor->display = eglGetDRMDisplayMESA(glamor->fd); eglBindAPI(EGL_OPENGL_API); LogMessageVerb(X_INFO, 0, "%s glCreateProgramObjectARB=%p", __FUNCTION__, *(&glCreateProgramObjectARB)); From cb3b34ec53e00c6ca212891b314f473ee2f80a40 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 1 Jul 2011 22:54:45 +0800 Subject: [PATCH 153/462] glamor-ddx: Add missed drmmode_crtc_destroy function. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor_crtc.c | 16 +++++++++++++++- hw/xfree86/glamor/glamor_ddx.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index aba9b2c29..1f0396dbf 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -613,6 +613,20 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, size, red, green, blue); } +static void +drmmode_crtc_destroy(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + ScrnInfoPtr scrn = crtc->scrn; + if (drmmode_crtc->cursor) { + drmmode_hide_cursor(crtc); + glDeleteTextures(1, &drmmode_crtc->cursor_tex); + glamor_destroy_cursor(scrn, drmmode_crtc->cursor); + } + free(drmmode_crtc->cursor); + crtc->driver_private = NULL; +} static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .dpms = drmmode_crtc_dpms, @@ -629,7 +643,7 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = { .shadow_destroy = drmmode_crtc_shadow_destroy, #endif .gamma_set = drmmode_crtc_gamma_set, - .destroy = NULL, /* XXX */ + .destroy = drmmode_crtc_destroy }; diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index 6f8de11ac..0e164d3b7 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -9,6 +9,7 @@ Bool glamor_load_cursor(ScrnInfoPtr scrn, void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR image, uint32_t *handle, uint32_t *pitch); EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height); +void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor); Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); void drmmode_closefb(ScrnInfoPtr scrn); From da66a76f276eccee90855bc0cb28092c3755ed7b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 1 Jul 2011 23:48:21 +0800 Subject: [PATCH 154/462] Revert "glamor: Don't need to read dest if op is SRC or CLEAR." This reverts commit eb16fe0b7c8ea27b5cf9122d02e48bf585495228. As currently glamor_prepare_access/finish_access will touch the whole pixmap, not just the request region, then write only mode will not work correctly. We may need to revisit all fallback case, and convert the image to the right size before do the prepare/finish processing. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 72e0f83c6..30cc50739 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1144,7 +1144,6 @@ glamor_composite(CARD8 op, PicturePtr temp_src = source, temp_mask = mask; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; glamor_composite_rect_t rect; - glamor_access_t dest_access; x_temp_src = x_source; y_temp_src = y_source; @@ -1266,12 +1265,7 @@ fail: glUseProgramObjectARB(0); glDisable(GL_BLEND); - - if (op == PictOpSrc || op == PictOpClear) - dest_access = GLAMOR_ACCESS_WO; - else - dest_access = GLAMOR_ACCESS_RW; - if (glamor_prepare_access_picture(dest, dest_access)) { + if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO)) { if (!mask || From fc23334e54b0b90d2f00b017a03cf47b70dc71aa Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 1 Jul 2011 23:51:42 +0800 Subject: [PATCH 155/462] glamor: Optimize fallback case for the polylines. When fallback to cpu for the polylines procedure, we can just download required region to CPU rather than to download the whole pixmap. This significant improve the performance if we have to fallback, for example do non-solid filling in the game Mines. Signed-off-by: Zhigang Gong --- glamor/glamor_polylines.c | 73 +++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 914961161..3fdb26426 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -49,6 +49,13 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, xRectangle *rects; int x1, x2, y1, y2; int i; + int x_min = MAXSHORT; + int x_max = MINSHORT; + int y_min = MAXSHORT; + int y_max = MINSHORT; + DrawablePtr temp_dest; + PixmapPtr temp_pixmap; + GCPtr temp_gc; /* 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 @@ -103,16 +110,70 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, return; fail: + for(i = 0; i < n; i++) + { + if (x_min > points[i].x) + x_min = points[i].x; + if (x_max < points[i].x) + x_max = points[i].x; + + if (y_min > points[i].y) + y_min = points[i].y; + if (y_max < points[i].y) + y_max = points[i].y; + } + + temp_pixmap = drawable->pScreen->CreatePixmap(drawable->pScreen, + x_max - x_min + 1, y_max - y_min + 1, + drawable->depth, + 0); + if (temp_pixmap) { + temp_dest = &temp_pixmap->drawable; + temp_gc = GetScratchGC(temp_dest->depth, temp_dest->pScreen); + ValidateGC(temp_dest, temp_gc); + for(i = 0; i < n; i++) + { + points[i].x -= x_min; + points[i].y -= y_min; + } + (void)glamor_copy_area(drawable, + temp_dest, + temp_gc, + x_min, y_min, + x_max - x_min + 1, y_max - y_min + 1, + 0, 0); + + } + else + temp_dest = drawable; + if (gc->lineWidth == 0) { - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access(temp_dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { - fbPolyLine(drawable, gc, mode, n, points); + fbPolyLine(temp_dest, gc, mode, n, points); glamor_finish_access_gc(gc); } - glamor_finish_access(drawable); + glamor_finish_access(temp_dest); } - return; - } + } + else { /* fb calls mi functions in the lineWidth != 0 case. */ - fbPolyLine(drawable, gc, mode, n, points); + fbPolyLine(drawable, gc, mode, n, points); + } + if (temp_dest != drawable) { + (void)glamor_copy_area(temp_dest, + drawable, + temp_gc, + 0, 0, + x_max - x_min + 1, y_max - y_min + 1, + x_min, y_min); + drawable->pScreen->DestroyPixmap(temp_pixmap); + for(i = 0; i < n; i++) + { + points[i].x += x_min; + points[i].y += y_min; + } + + FreeScratchGC(temp_gc); + } } From d49d48257917a4a900c84dae111d3f5e761a8d89 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 2 Jul 2011 14:47:38 +0800 Subject: [PATCH 156/462] glamor: Fix multiple crtc setup. Now, support dual crtc configuration. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor_crtc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 1f0396dbf..cf4940291 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -1352,10 +1352,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) if (!crtc->enabled) continue; -#if 0 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); -#endif } return TRUE; From 477a54bc9ed8f252b3a42af8ac01ef1da7b5ab6b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 7 Jul 2011 14:47:51 +0800 Subject: [PATCH 157/462] glamor: Fixed two unintialized warnings. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 7 ++++++- glamor/glamor_polylines.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 2408e3aae..9e2be123e 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -309,7 +309,7 @@ glamor_copy_n_to_n(DrawablePtr src, void *closure) { glamor_access_t dst_access; - PixmapPtr dst_pixmap, src_pixmap, temp_pixmap; + PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; DrawablePtr temp_src = src; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; BoxRec bound; @@ -361,6 +361,11 @@ glamor_copy_n_to_n(DrawablePtr src, temp_dy = -bound.y1; temp_src = &temp_pixmap->drawable; } + else { + temp_dx = dx; + temp_dy = dy; + temp_src = src; + } if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { goto done; diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 3fdb26426..d93b60209 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -55,7 +55,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, int y_max = MINSHORT; DrawablePtr temp_dest; PixmapPtr temp_pixmap; - GCPtr temp_gc; + GCPtr temp_gc = NULL; /* 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 From 77ecd366933bbe726a4a7e57e35b1510b675df8d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 7 Jul 2011 15:30:19 +0800 Subject: [PATCH 158/462] glamor: We don't need to check format in compositing. We already handle all format checking in pixmap uploading and converting, don't need to do that again. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 58 ------------------------------------------ 1 file changed, 58 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 30cc50739..41ee46b7d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -501,53 +501,6 @@ glamor_composite_with_copy(CARD8 op, 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: - 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: - 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: - return TRUE; - glamor_fallback("Bad dest format 0x%08x\n", picture->format); - return FALSE; - } -} - static void glamor_setup_composite_vbo(ScreenPtr screen) { @@ -815,10 +768,6 @@ glamor_composite_with_shader(CARD8 op, 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) { @@ -836,13 +785,6 @@ glamor_composite_with_shader(CARD8 op, goto fail; #endif } - if ((mask_status != GLAMOR_UPLOAD_PENDING) - && !good_mask_format(mask)) { - goto fail; - } - } - if (!good_dest_format(dest)) { - goto fail; } #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD if (source_status == GLAMOR_UPLOAD_PENDING From f961390db6fa0707895effb2e7672edda575f8ec Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 7 Jul 2011 15:31:35 +0800 Subject: [PATCH 159/462] glamor: Don't need to pad the tile image if pixmap is ni texture. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 31734bed0..da8b90b21 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -242,12 +242,10 @@ Bool glamor_prepare_access_gc(GCPtr gc) { if (gc->stipple) { - glamor_fallback("has stipple %p\n", gc->stipple); if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO)) return FALSE; } if (gc->fillStyle == FillTiled) { - glamor_fallback("has tile pixmap %p\n", gc->tile.pixmap); if (!glamor_prepare_access (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RO)) { if (gc->stipple) @@ -353,16 +351,20 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) } #endif if (changes & GCTile) { - if (!gc->tileIsPixel && FbEvenTile(gc->tile.pixmap->drawable.width * - drawable->bitsPerPixel)) - { - glamor_fallback("GC %p tile changed %p.\n", gc, gc->tile.pixmap); - if (glamor_prepare_access(&gc->tile.pixmap->drawable, + if (!gc->tileIsPixel) { + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(gc->tile.pixmap); + if ((!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + && FbEvenTile(gc->tile.pixmap->drawable.width * + drawable->bitsPerPixel)) + { + glamor_fallback("GC %p tile changed %p.\n", gc, gc->tile.pixmap); + if (glamor_prepare_access(&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW)) { fbPadPixmap(gc->tile.pixmap); glamor_finish_access(&gc->tile.pixmap->drawable); - } - } + } + } + } /* Mask out the GCTile change notification, now that we've done FB's * job for it. */ @@ -373,7 +375,6 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) /* We can't inline stipple handling like we do for GCTile because * it sets fbgc privates. */ - glamor_fallback("GC %p stipple changed %p.\n", gc, gc->stipple); if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { fbValidateGC(gc, changes, drawable); glamor_finish_access(&gc->stipple->drawable); From 7fbdc60fd4eb94c02b0b89d05cfe0243c3562ec1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 7 Jul 2011 15:32:39 +0800 Subject: [PATCH 160/462] glamor: comment out the message when creating a system memory pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 6bab8c124..2eec6f536 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -130,9 +130,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, NULL); +#if 0 if (usage != GLAMOR_CREATE_PIXMAP_CPU) glamor_fallback("choose cpu memory for pixmap %p ," " %d x %d depth %d\n", pixmap, w, h, depth); +#endif } else pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); From fe0a6a29300055f8288c9d1f470fd3e24f5bb3bb Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 7 Jul 2011 16:54:18 +0800 Subject: [PATCH 161/462] glamor: Should return when done gl drawing. Signed-off-by: Zhigang Gong --- glamor/glamor_setspans.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 253f20345..9bc7d1567 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -84,10 +84,11 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, } drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } -fail: - glDisable(GL_SCISSOR_TEST); glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(GXcopy); + glDisable(GL_SCISSOR_TEST); + return; +fail: glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); From 1caf741a4a41ef46a43980ba0be897770fea13db Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 20 Jul 2011 13:02:28 +0800 Subject: [PATCH 162/462] glamor: Fixed a bug when computing the bounds of boxes. Signed-off-by: Zhigang Gong --- glamor/glamor_utils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 2c6563232..30432cf1f 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -134,11 +134,11 @@ glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) if (x_min > boxes[i].x1) x_min = boxes[i].x1; if (y_min > boxes[i].y1) - x_min = boxes[i].y1; + y_min = boxes[i].y1; if (x_max < boxes[i].x2) x_max = boxes[i].x2; - if (y_max > boxes[i].y2) + if (y_max < boxes[i].y2) y_max = boxes[i].y2; } bound->x1 = x_min; From 5c4d53c5126bb9f603d04dac6874280b527319f5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 20 Jul 2011 13:06:23 +0800 Subject: [PATCH 163/462] glamor: Implement delayed solid filling. When we need to solid fill an entire pixmap with a specific color, we do not need to draw it immediately. We can defer it to the following occasions: 1. The pixmap will be used as source, then we can just use a shader to instead of one copyarea. 2. The pixmap will be used as target, then we can do the filling just before drawing new pixel onto it. The filling and drawing will have the same target texture, we can save one time of fbo context switching. Actually, for the 2nd case, we have opportunity to further optimize it. We can just fill the untouched region. By applying this patch, the cairo-trace for the firefox-planet-gnome's rendering time decrease to 14seconds from 16 seconds. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 5 ++- glamor/glamor_copyarea.c | 69 ++++++++++++++++++++++++++-------------- glamor/glamor_fill.c | 22 ++++++++++--- glamor/glamor_getspans.c | 1 + glamor/glamor_pixmap.c | 68 ++++++++++++++++++++++++++++++++++++--- glamor/glamor_priv.h | 48 ++++++++++++++++++++++++++-- glamor/glamor_putimage.c | 3 +- glamor/glamor_render.c | 48 ++++++++++++++++++---------- glamor/glamor_setspans.c | 3 +- glamor/glamor_tile.c | 56 ++++++++++++++++++-------------- 10 files changed, 246 insertions(+), 77 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 2eec6f536..695230885 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -98,6 +98,7 @@ glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int te glamor_set_pixmap_texture(pixmap, w, h, tex); glamor_priv->screen_fbo = pixmap_priv->fb; + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } @@ -119,7 +120,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; - if (!glamor_check_fbo_width_height(w,h) + if (!glamor_check_fbo_width_height(w,h) || !glamor_check_fbo_depth(depth) || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. @@ -201,6 +202,7 @@ glamor_create_screen_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->gl_fbo = 1; pixmap_priv->gl_tex = 1; pixmap_priv->container = pixmap; + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; screen->CreatePixmap = glamor_create_pixmap; return pixmap; @@ -369,6 +371,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_putimage_shaders(screen); glamor_init_finish_access_shaders(screen); glamor_glyphs_init(screen); + glamor_pixmap_init(screen); return TRUE; diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 9e2be123e..4cbb3c66b 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -59,6 +59,9 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + if (src_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) + return FALSE; + if (gc) { if (gc->alu != GXcopy) { glamor_delayed_fallback(screen, "non-copy ALU\n"); @@ -78,6 +81,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, if (glamor_set_destination_pixmap(dst_pixmap)) { return FALSE; } + glamor_validate_pixmap(dst_pixmap); glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); @@ -130,6 +134,7 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv; int x_off, y_off, i; if (src != dst) { glamor_delayed_fallback(screen, "src != dest\n"); @@ -147,6 +152,9 @@ glamor_copy_n_to_n_copypixels(DrawablePtr src, } } + pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + if (pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) + return TRUE; if (glamor_set_destination_pixmap(dst_pixmap)) { glamor_delayed_fallback(screen, "dst has no fbo.\n"); return FALSE; @@ -234,37 +242,47 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_set_alu(gc->alu); if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fail; + if (gc->alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); + glamor_validate_pixmap(src_pixmap); + } + } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(dst_pixmap); + pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); 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; - dy += src_y_off; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); - glEnable(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - assert(GLEW_ARB_fragment_shader); - glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); - + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); + dx += src_x_off; + dy += src_y_off; + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); + } + else { + GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); + } + for (i = 0; i < nbox; i++) { - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, @@ -273,11 +291,12 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_xscale, src_yscale, - box[i].x1 + dx, box[i].y1 + dy, - box[i].x2 + dx, box[i].y2 + dy, - glamor_priv->yInverted, - texcoords); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) + glamor_set_normalize_tcoords(src_xscale, src_yscale, + box[i].x1 + dx, box[i].y1 + dy, + box[i].x2 + dx, box[i].y2 + dy, + glamor_priv->yInverted, + texcoords); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } @@ -285,8 +304,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glUseProgramObjectARB(0); glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + } return TRUE; fail: @@ -352,6 +373,7 @@ glamor_copy_n_to_n(DrawablePtr src, if (!temp_src) goto fail; glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + temp_src = &temp_pixmap->drawable; fbCopyNtoN(src, temp_src, gc, box, nbox, temp_dx + bound.x1, temp_dy + bound.y1, reverse, upsidedown, bitplane, @@ -359,7 +381,6 @@ glamor_copy_n_to_n(DrawablePtr src, glamor_transform_boxes(box, nbox, bound.x1, bound.y1); temp_dx = -bound.x1; temp_dy = -bound.y1; - temp_src = &temp_pixmap->drawable; } else { temp_dx = dx; diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index a41837b3a..393f651ed 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -154,7 +154,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat xscale, yscale; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("dest has no fbo.\n"); + glamor_fallback("dest %p has no fbo.\n", pixmap); goto fail; } glamor_set_alu(alu); @@ -163,15 +163,29 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, goto fail; } - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - - glUseProgramObjectARB(glamor_priv->solid_prog); glamor_get_rgba_from_pixel(fg_pixel, &color[0], &color[1], &color[2], &color[3], format_for_pixmap(pixmap)); +#ifdef GLAMOR_DELAYED_FILLING + if (x == 0 && y == 0 + && width == pixmap->drawable.width + && height == pixmap->drawable.height + && pixmap_priv->fb != glamor_priv->screen_fbo ) { + pixmap_priv->pending_op.type = GLAMOR_PENDING_FILL; + memcpy(&pixmap_priv->pending_op.fill.color4fv, + color, 4*sizeof(GLfloat)); + pixmap_priv->pending_op.fill.colori = fg_pixel; + return TRUE; + } +#endif + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); + + glUseProgramObjectARB(glamor_priv->solid_prog); + glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 7fe05f993..237c1e789 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -64,6 +64,7 @@ glamor_get_spans(DrawablePtr drawable, } glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); for (i = 0; i < count; i++) { diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index c76920a26..924a17369 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -26,14 +26,71 @@ glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, *y = 0; } + +static void +_glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, + glamor_pixmap_private *pixmap_priv) +{ + GLfloat vertices[8]; +// glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); + glEnableClientState(GL_VERTEX_ARRAY); + glUseProgramObjectARB(glamor_priv->solid_prog); + glUniform4fvARB(glamor_priv->solid_color_uniform_location, + 1, pixmap_priv->pending_op.fill.color4fv); + vertices[0] = -1; + vertices[1] = -1; + vertices[2] = 1; + vertices[3] = -1; + vertices[4] = 1; + vertices[5] = 1; + vertices[6] = -1; + vertices[7] = 1; + glDrawArrays(GL_QUADS, 0, 4); + glDisableClientState(GL_VERTEX_ARRAY); + glUseProgramObjectARB(0); + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; +} + + +glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { + NULL, + _glamor_pixmap_validate_filling +}; + +void +glamor_pixmap_init(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; +} + +void +glamor_validate_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_validate_function_t validate_op; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + + validate_op = glamor_priv->pixmap_validate_funcs[pixmap_priv->pending_op.type]; + if (validate_op) { + (*validate_op)(glamor_priv, pixmap_priv); + } +} + void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0, 0, pixmap_priv->container->drawable.width, pixmap_priv->container->drawable.height); + } int @@ -49,9 +106,11 @@ glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv) int glamor_set_destination_pixmap(PixmapPtr pixmap) { + int err; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - return glamor_set_destination_pixmap_priv(pixmap_priv); + err = glamor_set_destination_pixmap_priv(pixmap_priv); + return err; } Bool @@ -376,7 +435,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; - + /* XXX we may don't need to validate it on GPU here, + * we can just validate it on CPU. */ if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, @@ -395,7 +455,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) pixmap->drawable.depth); stride = pixmap->devKind; - + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); switch (access) { case GLAMOR_ACCESS_RO: gl_access = GL_READ_ONLY_ARB; @@ -415,7 +476,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } 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); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 4b0037333..b7fcfbdeb 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -149,6 +149,10 @@ enum shader_in { SHADER_IN_COUNT, }; +struct glamor_screen_private; +struct glamor_pixmap_private; +typedef void (*glamor_pixmap_validate_function_t)(struct glamor_screen_private*, + struct glamor_pixmap_private*); #define GLAMOR_CREATE_PIXMAP_CPU 0x100 typedef struct glamor_screen_private { CloseScreenProcPtr saved_close_screen; @@ -197,7 +201,7 @@ typedef struct glamor_screen_private { [SHADER_IN_COUNT]; Bool has_source_coords, has_mask_coords; int render_nr_verts; - + glamor_pixmap_validate_function_t *pixmap_validate_funcs; glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; @@ -220,9 +224,34 @@ typedef enum glamor_access { * @pbo: attached pbo. * @access_mode: access mode during the prepare/finish pair. * @pict_format: the corresponding picture's format. + * #pending_op: currently only support pending filling. * @container: The corresponding pixmap's pointer. **/ +#define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ + (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ + && (pixmap_priv->pending_op.type != GLAMOR_PENDING_NONE)) + +#define GLAMOR_PIXMAP_PRIV_NO_PENDING(pixmap_priv) \ + (pixmap_priv->pending_op.type == GLAMOR_PENDING_NONE) + +enum _glamor_pending_op_type{ + GLAMOR_PENDING_NONE, + GLAMOR_PENDING_FILL +}; + +typedef struct _glamor_pending_fill { + unsigned int type; + GLfloat color4fv[4]; + CARD32 colori; +} glamor_pending_fill; + +typedef union _glamor_pending_op { + unsigned int type; + glamor_pending_fill fill; +} glamor_pending_op; + + typedef struct glamor_pixmap_private { unsigned char gl_fbo:1; unsigned char gl_tex:1; @@ -233,9 +262,20 @@ typedef struct glamor_pixmap_private { GLuint pbo; glamor_access_t access_mode; PictFormatShort pict_format; + glamor_pending_op pending_op; PixmapPtr container; } glamor_pixmap_private; +#define GLAMOR_CHECK_PENDING_FILL(_glamor_priv_, _pixmap_priv_) do \ + { \ + if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ + glUseProgramObjectARB(_glamor_priv_->solid_prog); \ + glUniform4fvARB(_glamor_priv_->solid_color_uniform_location, 1, \ + _pixmap_priv_->pending_op.fill.color4fv); \ + } \ + } while(0) + + /* * Pixmap dynamic status, used by dynamic upload feature. * @@ -678,6 +718,8 @@ glamor_triangles (CARD8 op, /* glamor_pixmap.c */ +void +glamor_pixmap_init(ScreenPtr screen); /** * Download a pixmap's texture to cpu memory. If success, * One copy of current pixmap's texture will be put into @@ -724,7 +766,8 @@ glamor_upload_picture_to_texture(PicturePtr picture); void glamor_destroy_upload_pixmap(PixmapPtr pixmap); - +void +glamor_validate_pixmap(PixmapPtr pixmap); int glamor_create_picture(PicturePtr picture); @@ -753,6 +796,7 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD +#define GLAMOR_DELAYED_FILLING #include"glamor_utils.h" diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index e61425d11..0a910509c 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -296,6 +296,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } /* XXX consider to reuse a function to do the following work. */ + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -303,7 +305,6 @@ 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); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 41ee46b7d..f0a6e880c 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -395,16 +395,8 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, } static void -glamor_set_composite_solid(PicturePtr picture, GLint uniform_location) +glamor_set_composite_solid(float *color, GLint uniform_location) { - 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; - glUniform4fvARB(uniform_location, 1, color); } @@ -696,6 +688,7 @@ glamor_composite_with_shader(CARD8 op, enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; + GLfloat source_solid_color[4], mask_solid_color[4]; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); @@ -707,6 +700,12 @@ glamor_composite_with_shader(CARD8 op, if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeSolidFill) { key.source = SHADER_SOURCE_SOLID; + glamor_get_rgba_from_pixel(source->pSourcePict->solidFill.color, + &source_solid_color[0], + &source_solid_color[1], + &source_solid_color[2], + &source_solid_color[3], + PICT_a8r8g8b8); } else { glamor_fallback("gradient source\n"); goto fail; @@ -718,6 +717,12 @@ glamor_composite_with_shader(CARD8 op, if (!mask->pDrawable) { if (mask->pSourcePict->type == SourcePictTypeSolidFill) { key.mask = SHADER_MASK_SOLID; + glamor_get_rgba_from_pixel(mask->pSourcePict->solidFill.color, + &mask_solid_color[0], + &mask_solid_color[1], + &mask_solid_color[2], + &mask_solid_color[3], + PICT_a8r8g8b8); } else { glamor_fallback("gradient mask\n"); goto fail; @@ -767,6 +772,10 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("no texture in source\n"); goto fail; #endif + } + else if (source_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) { + key.source = SHADER_SOURCE_SOLID; + memcpy(source_solid_color, source_pixmap_priv->pending_op.fill.color4fv, 4 * sizeof(float)); } } if (key.mask == SHADER_MASK_TEXTURE || @@ -785,6 +794,10 @@ glamor_composite_with_shader(CARD8 op, goto fail; #endif } + else if (mask_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) { + key.mask = SHADER_MASK_SOLID; + memcpy(mask_solid_color, mask_pixmap_priv->pending_op.fill.color4fv, 4 * sizeof(float)); + } } #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD if (source_status == GLAMOR_UPLOAD_PENDING @@ -853,10 +866,11 @@ glamor_composite_with_shader(CARD8 op, } } #endif + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + glamor_validate_pixmap(dest_pixmap); if (!glamor_set_composite_op(screen, op, dest, mask)) { goto fail; } - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); shader = glamor_lookup_composite_shader(screen, &key); if (shader->prog == 0) { @@ -866,13 +880,13 @@ glamor_composite_with_shader(CARD8 op, glUseProgramObjectARB(shader->prog); if (key.source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(source, shader->source_uniform_location); + glamor_set_composite_solid(source_solid_color, 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); + glamor_set_composite_solid(mask_solid_color, shader->mask_uniform_location); } else { glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); } @@ -888,14 +902,14 @@ glamor_composite_with_shader(CARD8 op, - if (source_pixmap) { + if (glamor_priv->has_source_coords) { glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, &source_y_off); pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); glamor_picture_get_matrixf(source, src_matrix); } - if (mask_pixmap) { + if (glamor_priv->has_mask_coords) { glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); @@ -944,14 +958,14 @@ glamor_composite_with_shader(CARD8 op, 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++) { int vx1 = box[i].x1 + dest_x_off; int vx2 = box[i].x2 + dest_x_off; int vy1 = box[i].y1 + dest_y_off; int vy2 = box[i].y2 + dest_y_off; - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, vx1, vy1, vx2, vy2, + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, vx1, vy1, vx2, vy2, glamor_priv->yInverted, vertices); if (key.source != SHADER_SOURCE_SOLID) { @@ -1260,7 +1274,7 @@ glamor_create_mask_picture(ScreenPtr screen, pixmap = screen->CreatePixmap(screen, 0, 0, pict_format->depth, - 0); + GLAMOR_CREATE_PIXMAP_CPU); if (!pixmap) return 0; picture = CreatePicture(0, &pixmap->drawable, pict_format, diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 9bc7d1567..14a24378f 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -52,9 +52,10 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, drawable->depth); goto fail; } - if (glamor_set_destination_pixmap(dest_pixmap)) goto fail; + + glamor_validate_pixmap(dest_pixmap); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; glamor_set_alu(gc->alu); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 5bfdd7341..a78c30194 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -107,7 +107,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_fallback("dest has no fbo.\n"); goto fail; } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { /* XXX dynamic uploading candidate. */ glamor_fallback("Non-texture tile pixmap\n"); @@ -118,48 +117,59 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; } - + if (alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); + glamor_validate_pixmap(tile); + } + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(pixmap); pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); glamor_set_alu(alu); - glUseProgramObjectARB(glamor_priv->tile_prog); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glEnable(GL_TEXTURE_2D); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + glUseProgramObjectARB(glamor_priv->tile_prog); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glEnable(GL_TEXTURE_2D); + glamor_set_normalize_tcoords(src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); + glClientActiveTexture(GL_TEXTURE0); + glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else { + GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); + } + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, x1, y1,x2, y2, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_xscale, src_yscale, - tile_x1, tile_y1, - tile_x2, tile_y2, - glamor_priv->yInverted, - source_texcoords); - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + } glDisableClientState(GL_VERTEX_ARRAY); glUseProgramObjectARB(0); - glDisable(GL_TEXTURE_2D); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); return TRUE; From 1f3f3baf1469e74767474ddb383e92502384de80 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 20 Jul 2011 13:35:25 +0800 Subject: [PATCH 164/462] glamor: Avoid 2D bitblit if possible. It turns out that the use of fbo blit is one of the root cause which lead to slow drawing, especially slow filling rects. We guess there should be a performance bug in the mesa driver or even in the kernel drm driver. Currently, the only thing glamor can do is to avoid calling those functions. We check whether the copy source and destination has overlapped region, if it has, we have to call fbo blit function. If it has not, we can load the source texture directly and draw it to the target texture. We totally don't need the glCopyPixels here, so remove it. By apply this patch, the rendering time of firefox-planet-gnome decrease to 10.4 seconds. At the same platform, uxa driver get 13 seconds. This is the first time we get better performance than uxa driver. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 158 ++++++++++----------------------------- 1 file changed, 38 insertions(+), 120 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 4cbb3c66b..c8ccaaef1 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -47,15 +47,10 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int dst_x_off, dst_y_off, src_x_off, src_y_off, i; - if (src == dst) { - glamor_delayed_fallback(screen,"src == dest\n"); - return FALSE; - } - if (!GLEW_EXT_framebuffer_blit) { glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n"); return FALSE; - } + } src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); @@ -121,78 +116,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, return TRUE; } -static Bool -glamor_copy_n_to_n_copypixels(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy) -{ - ScreenPtr screen = dst->pScreen; - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_pixmap_private *pixmap_priv; - int x_off, y_off, i; - if (src != dst) { - glamor_delayed_fallback(screen, "src != dest\n"); - return FALSE; - } - - if (gc) { - if (gc->alu != GXcopy) { - glamor_delayed_fallback(screen,"non-copy ALU\n"); - return FALSE; - } - if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_delayed_fallback(screen,"non-solid planemask\n"); - return FALSE; - } - } - - pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - if (pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) - return TRUE; - 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, - 0, dst_pixmap->drawable.height, - -1, 1); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - glamor_get_drawable_deltas(dst, dst_pixmap, &x_off, &y_off); - - for (i = 0; i < nbox; i++) { - if(glamor_priv->yInverted) { - glRasterPos2i(box[i].x1 + x_off, - box[i].y1 + y_off); - glCopyPixels(box[i].x1 + dx + x_off, - box[i].y1 + dy + y_off, - box[i].x2 - box[i].x1, - box[i].y2 - box[i].y1, - GL_COLOR); - } else { - int flip_y1 = dst_pixmap->drawable.height - box[i].y2 + y_off; - glRasterPos2i(box[i].x1 + x_off, - flip_y1); - glCopyPixels(box[i].x1 + dx + x_off, - flip_y1 - dy, - box[i].x2 - box[i].x1, - box[i].y2 - box[i].y1, - GL_COLOR); - } - } - return TRUE; -} - static Bool glamor_copy_n_to_n_textured(DrawablePtr src, DrawablePtr dst, @@ -213,21 +136,17 @@ glamor_copy_n_to_n_textured(DrawablePtr src, int src_x_off, src_y_off, dst_x_off, dst_y_off; enum glamor_pixmap_status src_status = GLAMOR_NONE; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; + int flush_needed = 0; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - if (src == dst) { - glamor_delayed_fallback(dst->pScreen, "same src/dst\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 (!src_pixmap_priv->gl_tex) { + if (!src_pixmap_priv->gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); goto fail; @@ -237,6 +156,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, goto fail; #endif } + else + flush_needed = 1; if (gc) { glamor_set_alu(gc->alu); @@ -246,7 +167,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); glamor_validate_pixmap(src_pixmap); } - } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); @@ -283,6 +203,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, } for (i = 0; i < nbox; i++) { + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, @@ -308,6 +229,9 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } + /* The source texture is bound to a fbo, we have to flush it here. */ + if (flush_needed) + glFlush(); return TRUE; fail: @@ -337,8 +261,14 @@ glamor_copy_n_to_n(DrawablePtr src, ScreenPtr screen; int temp_dx = dx; int temp_dy = dy; + int src_x_off, src_y_off, dst_x_off, dst_y_off; + int i; + int overlaped = 0; + dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + src_pixmap = glamor_get_drawable_pixmap(src); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { @@ -346,19 +276,29 @@ glamor_copy_n_to_n(DrawablePtr src, goto fail; } - if (glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); + + if (src_pixmap_priv->fb == dst_pixmap_priv->fb) { + int x_shift = abs(src_x_off - dx - dst_x_off); + int y_shift = abs(src_y_off - dy - dst_y_off); + for ( i = 0; i < nbox; i++) + { + if (x_shift < abs(box[i].x2 - box[i].x1) + && y_shift < abs(box[i].y2 - box[i].y1)) { + overlaped = 1; + break; + } + } + } + /* XXX need revisit to handle overlapped area copying. */ + + if ( overlaped + && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { goto done; return; } - if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)){ - goto done; - return; - } - - src_pixmap = glamor_get_drawable_pixmap(src); - src_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - glamor_calculate_boxes_bound(&bound, box, nbox); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) @@ -370,7 +310,7 @@ glamor_copy_n_to_n(DrawablePtr src, bound.y2 - bound.y1, src_pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); - if (!temp_src) + if (!temp_pixmap) goto fail; glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); temp_src = &temp_pixmap->drawable; @@ -391,6 +331,7 @@ glamor_copy_n_to_n(DrawablePtr src, if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { goto done; } + fail: glamor_report_delayed_fallbacks(src->pScreen); @@ -406,7 +347,8 @@ glamor_copy_n_to_n(DrawablePtr src, dst_access = GLAMOR_ACCESS_WO; if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { - if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { + if (dst == src + || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); @@ -428,34 +370,10 @@ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, int srcx, int srcy, int width, int height, int dstx, int dsty) { -#if 0 - ScreenPtr screen = dst->pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); -#endif RegionPtr region; - region = miDoCopy(src, dst, gc, srcx, srcy, width, height, dstx, dsty, glamor_copy_n_to_n, 0, NULL); return region; - -#if 0 -fail: - glamor_fallback("glamor_copy_area from %p to %p (%c,%c)\n", src, dst, - glamor_get_drawable_location(src), - glamor_get_drawable_location(dst)); - region = NULL; - if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { - if (glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { - region = fbCopyArea(src, dst, gc, srcx, srcy, width, height, - dstx, dsty); - glamor_finish_access(src); - } - glamor_finish_access(dst); - } - return region; -#endif } From 01489f9da9aa357c59799d4d41c7ca96b4cbd1d8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 20 Jul 2011 14:02:15 +0800 Subject: [PATCH 165/462] glamor: Add simple introduction of how to setup glamor xserver. Signed-off-by: Zhigang Gong --- README | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/README b/README index b2499a059..05effbeba 100644 --- a/README +++ b/README @@ -1,4 +1,83 @@ - X Server + Glamor setup + +1. Prerequirement. +Please install makedepend and libudev-devel firstly. +Glamor need patch glew-1.5.8, here is the patch: + + +diff -ur ../Downloads/glew-1.5.8/Makefile glew-1.5.8/Makefile +--- ../Downloads/glew-1.5.8/Makefile 2011-01-31 22:17:27.000000000 +0800 ++++ glew-1.5.8/Makefile 2011-06-28 10:13:54.147700479 +0800 +@@ -63,8 +63,12 @@ + else + OPT = $(POPT) + endif +-INCLUDE = -Iinclude ++ ++NCLUDE = -Iinclude + CFLAGS = $(OPT) $(WARN) $(INCLUDE) $(CFLAGS.EXTRA) ++ifeq ($(NO_GLX), 1) ++CFLAGS += -D_NO_GLX_ ++endif + + LIB.SRCS = src/glew.c + LIB.OBJS = $(LIB.SRCS:.c=.o) +diff -ur ../Downloads/glew-1.5.8/src/glew.c glew-1.5.8/src/glew.c +--- ../Downloads/glew-1.5.8/src/glew.c 2011-01-31 22:17:27.000000000 +0800 ++++ glew-1.5.8/src/glew.c 2011-06-28 10:06:45.952700777 +0800 +@@ -11379,6 +11379,10 @@ + { + GLenum r; + if ( (r = glewContextInit()) ) return r; ++#if defined(_NO_GLX_) ++ return r; ++#endif ++ + #if defined(_WIN32) + return wglewContextInit(); + #elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ + + +As xserver's glx extension code has conflicts with glew's glx related +initialization, we have to disable it in glew currently. Please apply the +above patch to glew and then build the glew as follow which will +workaround the problem. + +glew-1.5.8# NO_GLX=1 make + +2. Build xserver-glamor. + +Then do the following steps one by one. +2.1. get latest glamor at github. + +2.2 Setup xorg development environment, use xserver-glamor to + replace the official xserver. + Here is the link of how to setup xorg development environment: + http://www.x.org/wiki/ModularDevelopersGuide + + For most of the packages, we prefer latest git version. Especially + for the mesa package. + + When build mesa, use the following parameters: (assume you want to + install the experimental xorg to /opt/gfx-test) +#mesa/./autogen.sh --prefix=/opt/gfx-test --with-egl-platforms=drm --disable-gallium --disable-gallium-egl + + build xserver-glamor as below: +#xserver-glamor/./autogen.sh --disable-glx --enable-kdrive --enable-xephyr + + Once you finish all the building process, you can have a try as below: +xserver-glamor#startx -- `pwd`/hw/xfree86/Xorg If you can find the + following messages on the console, then everything should work correctly. +Mesa: Initializing x86-64 optimizations + + +3. Restrictions: + +Currently, glamor doesn't support glx extension, will be fixed in the future. + +Glamor setup done. + + X Server The X server accepts requests from client applications to create windows, which are (normally rectangular) "virtual screens" that the client program From 9b667ffd564910ff7373547ce2f8d4a7c5d71137 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 20 Jul 2011 14:33:00 +0800 Subject: [PATCH 166/462] glamor: Use small internal texture format if possible. Reduce some texture memory requirement and also save some bandwidth. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 6 +++--- glamor/glamor_pixmap.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 695230885..33a33d690 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -151,10 +151,10 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) return pixmap; - /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. - * FBOs, which EXT_fbo forgot to do. - */ switch (depth) { + case 8: + format = GL_ALPHA; + break; case 24: format = GL_RGB; break; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 924a17369..0f85d9687 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -199,7 +199,20 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); unsigned int stride, row_length; void *texels; - GLenum iformat = GL_RGBA; + GLenum iformat; + + switch (pixmap->drawable.depth) { + case 8: + iformat = GL_ALPHA; + break; + case 24: + iformat = GL_RGB; + break; + default: + iformat = GL_RGBA; + break; + } + stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; From 0ef1698be22750fb14418bd418114fc63039db0c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 21 Jul 2011 16:18:48 +0800 Subject: [PATCH 167/462] glamor: Fix one bug for Xephyr. Xephyr doesn't has a bounded valid texture. It seems that we can't load texture 0 directly sometimes. Especially in the copyarea, function if that is the case, we prefer to use fbo blit to read the screen pixmap rather than load the bound texture. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 +- glamor/glamor_copyarea.c | 3 ++- glamor/glamor_render.c | 8 ++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 33a33d690..f3a83fa04 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -200,7 +200,7 @@ glamor_create_screen_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv->tex = 0; pixmap_priv->gl_fbo = 1; - pixmap_priv->gl_tex = 1; + pixmap_priv->gl_tex = 0; pixmap_priv->container = pixmap; pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index c8ccaaef1..c7d0d2163 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -293,7 +293,8 @@ glamor_copy_n_to_n(DrawablePtr src, } /* XXX need revisit to handle overlapped area copying. */ - if ( overlaped + if ((overlaped + || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex ) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { goto done; return; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f0a6e880c..a9015784e 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -765,7 +765,11 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("source == dest\n"); goto fail; } - if (!source_pixmap_priv || source_pixmap_priv->gl_tex == 0) { + if (!source_pixmap_priv || source_pixmap_priv->gl_fbo == 0) { + /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex + * equal to zero when the pixmap is screen pixmap. Then we may + * refer the tex zero directly latter in the composition. + * It seems that it works fine, but it may have potential problem*/ #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD source_status = GLAMOR_UPLOAD_PENDING; #else @@ -786,7 +790,7 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("mask == dest\n"); goto fail; } - if (!mask_pixmap_priv || mask_pixmap_priv->gl_tex == 0) { + if (!mask_pixmap_priv || mask_pixmap_priv->gl_fbo == 0) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD mask_status = GLAMOR_UPLOAD_PENDING; #else From 98f8ef5f991e3c9d4b434af9003c466ad1edc23e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 2 Aug 2011 15:51:46 +0800 Subject: [PATCH 168/462] glamor: Change to use official APIs rather than ARB version function. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 24 ++++++++------ glamor/glamor_copyarea.c | 4 +-- glamor/glamor_core.c | 68 ++++++++++++++++++++-------------------- glamor/glamor_fill.c | 22 ++++++------- glamor/glamor_pixmap.c | 48 ++++++++++++++-------------- glamor/glamor_putimage.c | 32 +++++++++---------- glamor/glamor_render.c | 40 +++++++++++------------ glamor/glamor_tile.c | 22 ++++++------- 8 files changed, 132 insertions(+), 128 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index f3a83fa04..b6789844d 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -74,10 +74,10 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) */ 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, - GL_COLOR_ATTACHMENT0_EXT, + glGenFramebuffers(1, &pixmap_priv->fb); + glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pixmap_priv->tex, 0); @@ -217,11 +217,11 @@ glamor_destroy_pixmap(PixmapPtr pixmap) if (pixmap->refcnt == 1) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv->fb) - glDeleteFramebuffersEXT(1, &pixmap_priv->fb); + glDeleteFramebuffers(1, &pixmap_priv->fb); if (pixmap_priv->tex) glDeleteTextures(1, &pixmap_priv->tex); if (pixmap_priv->pbo) - glDeleteBuffersARB(1, &pixmap_priv->pbo); + glDeleteBuffers(1, &pixmap_priv->pbo); dixFreePrivates(pixmap->devPrivates, PRIVATE_PIXMAP); } @@ -293,6 +293,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glewInit(); +#ifndef GLAMOR_GLES2 if (!GLEW_EXT_framebuffer_object) { ErrorF("GL_EXT_framebuffer_object required\n"); goto fail; @@ -305,14 +306,17 @@ glamor_init(ScreenPtr screen, unsigned int flags) ErrorF("GL_ARB_vertex_shader required\n"); goto fail; } - if (!GLEW_ARB_pixel_buffer_object) { - ErrorF("GL_ARB_pixel_buffer_object required\n"); - goto fail; - } if (!GLEW_EXT_bgra) { ErrorF("GL_EXT_bgra required\n"); goto fail; } +#endif + + if (!GLEW_ARB_pixel_buffer_object) { + ErrorF("GL_ARB_pixel_buffer_object required\n"); + goto fail; + } + if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, NULL)) { diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index c7d0d2163..acd1edc8c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -196,7 +196,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glUseProgramObjectARB(glamor_priv->finish_access_prog[0]); + glUseProgram(glamor_priv->finish_access_prog[0]); } else { GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); @@ -222,7 +222,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - glUseProgramObjectARB(0); + glUseProgram(0); glDisableClientState(GL_VERTEX_ARRAY); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index da8b90b21..d99560fd6 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -59,10 +59,10 @@ 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 = glGetUniformLocation(prog, "x_bias"); + uniform_locations->x_scale = glGetUniformLocation(prog, "x_scale"); + uniform_locations->y_bias = glGetUniformLocation(prog, "y_bias"); + uniform_locations->y_scale = glGetUniformLocation(prog, "y_scale"); } /* We don't use a full matrix for our transformations because it's @@ -73,10 +73,10 @@ 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); + glUniform1f(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f); + glUniform1f(uniform_locations->x_scale, 2.0f / pixmap->drawable.width); + glUniform1f(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f); + glUniform1f(uniform_locations->y_scale, -2.0f / pixmap->drawable.height); } GLint @@ -85,9 +85,9 @@ glamor_compile_glsl_prog(GLenum type, const char *source) GLint ok; GLint prog; - prog = glCreateShaderObjectARB(type); - glShaderSourceARB(prog, 1, (const GLchar **)&source, NULL); - glCompileShaderARB(prog); + prog = glCreateShader(type); + glShaderSource(prog, 1, (const GLchar **)&source, NULL); + glCompileShader(prog); glGetObjectParameterivARB(prog, GL_OBJECT_COMPILE_STATUS_ARB, &ok); if (!ok) { GLchar *info; @@ -165,22 +165,22 @@ glamor_init_finish_access_shaders(ScreenPtr screen) GLint fs_prog, vs_prog, avs_prog, aswizzle_prog; - glamor_priv->finish_access_prog[0] = glCreateProgramObjectARB(); - glamor_priv->finish_access_prog[1] = glCreateProgramObjectARB(); + glamor_priv->finish_access_prog[0] = glCreateProgram(); + glamor_priv->finish_access_prog[1] = glCreateProgram(); 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); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source); + glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); + glAttachShader(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->finish_access_prog[1], avs_prog); - glAttachObjectARB(glamor_priv->finish_access_prog[1], aswizzle_prog); + avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); + aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, aswizzle_source); + glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); + glAttachShader(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); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); + glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); ErrorF("Lack of framgment shader support.\n"); } @@ -191,16 +191,16 @@ glamor_init_finish_access_shaders(ScreenPtr screen) GLint sampler_uniform_location; 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); + glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[0]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); 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); + glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[1]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); } } @@ -218,10 +218,10 @@ glamor_finish_access(DrawablePtr drawable) } if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); - glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_EXT, 0); + glBindBuffer (GL_PIXEL_PACK_BUFFER_EXT, 0); + glBindBuffer (GL_PIXEL_UNPACK_BUFFER_EXT, 0); pixmap_priv->pbo_valid = FALSE; - glDeleteBuffersARB(1, &pixmap_priv->pbo); + glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; } else free(pixmap->devPrivate.ptr); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 393f651ed..14cce0c8c 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -122,20 +122,20 @@ glamor_init_solid_shader(ScreenPtr screen) "}\n"; GLint fs_prog, vs_prog; - glamor_priv->solid_prog = glCreateProgramObjectARB(); + glamor_priv->solid_prog = glCreateProgram(); if (GLEW_ARB_fragment_shader) { - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, solid_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, solid_fs); - glAttachObjectARB(glamor_priv->solid_prog, vs_prog); - glAttachObjectARB(glamor_priv->solid_prog, fs_prog); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs); + glAttachShader(glamor_priv->solid_prog, vs_prog); + glAttachShader(glamor_priv->solid_prog, fs_prog); } else { - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, solid_vs_only); - glAttachObjectARB(glamor_priv->solid_prog, vs_prog); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs_only); + glAttachShader(glamor_priv->solid_prog, vs_prog); } glamor_link_glsl_prog(glamor_priv->solid_prog); glamor_priv->solid_color_uniform_location = - glGetUniformLocationARB(glamor_priv->solid_prog, "color"); + glGetUniformLocation(glamor_priv->solid_prog, "color"); } Bool @@ -184,9 +184,9 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); - glUseProgramObjectARB(glamor_priv->solid_prog); + glUseProgram(glamor_priv->solid_prog); - glUniform4fvARB(glamor_priv->solid_color_uniform_location, 1, color); + glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -199,7 +199,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); - glUseProgramObjectARB(0); + glUseProgram(0); return TRUE; fail: glamor_set_alu(GXcopy); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 0f85d9687..0f13f09c2 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -35,8 +35,8 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, // glamor_set_destination_pixmap_priv_nc(pixmap_priv); glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - glUseProgramObjectARB(glamor_priv->solid_prog); - glUniform4fvARB(glamor_priv->solid_color_uniform_location, + glUseProgram(glamor_priv->solid_prog); + glUniform4fv(glamor_priv->solid_color_uniform_location, 1, pixmap_priv->pending_op.fill.color4fv); vertices[0] = -1; vertices[1] = -1; @@ -48,7 +48,7 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, vertices[7] = 1; glDrawArrays(GL_QUADS, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); - glUseProgramObjectARB(0); + glUseProgram(0); pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } @@ -223,7 +223,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { texels = NULL; - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); } else texels = pixmap->devPrivate.ptr; @@ -300,12 +300,12 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i 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]); + glUseProgram(glamor_priv->finish_access_prog[ax]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisable(GL_TEXTURE_2D); - glUseProgramObjectARB(0); + glUseProgram(0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); @@ -472,16 +472,16 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_validate_pixmap(pixmap); switch (access) { case GLAMOR_ACCESS_RO: - gl_access = GL_READ_ONLY_ARB; - gl_usage = GL_STREAM_READ_ARB; + gl_access = GL_READ_ONLY; + gl_usage = GL_STREAM_READ; break; case GLAMOR_ACCESS_WO: data = malloc(stride * pixmap->drawable.height); goto done; break; case GLAMOR_ACCESS_RW: - gl_access = GL_READ_WRITE_ARB; - gl_usage = GL_DYNAMIC_DRAW_ARB; + gl_access = GL_READ_WRITE; + gl_usage = GL_DYNAMIC_DRAW; break; default: ErrorF("Glamor: Invalid access code. %d\n", access); @@ -497,41 +497,41 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) 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, + glGenBuffers (1, &pixmap_priv->pbo); + glBindBuffer (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glBufferData (GL_PIXEL_PACK_BUFFER_EXT, stride * pixmap->drawable.height, NULL, gl_usage); glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); - data = glMapBufferARB (GL_PIXEL_PACK_BUFFER_EXT, gl_access); + data = glMapBuffer (GL_PIXEL_PACK_BUFFER_EXT, gl_access); pixmap_priv->pbo_valid = TRUE; if (!glamor_priv->yInverted) glPixelStorei(GL_PACK_INVERT_MESA, 0); - glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0); + glBindBuffer (GL_PIXEL_PACK_BUFFER_EXT, 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, + glGenBuffers(1, &pixmap_priv->pbo); + glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); + glBufferData(GL_PIXEL_PACK_BUFFER_EXT, stride * pixmap->drawable.height, - NULL, GL_STREAM_READ_ARB); + NULL, GL_STREAM_READ); glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); - read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB); + read = glMapBuffer(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY); 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); + glUnmapBuffer(GL_PIXEL_PACK_BUFFER_EXT); + glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, 0); pixmap_priv->pbo_valid = FALSE; - glDeleteBuffersARB(1, &pixmap_priv->pbo); + glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; } } @@ -555,7 +555,7 @@ _glamor_destroy_upload_pixmap(PixmapPtr pixmap) if (pixmap_priv->tex) glDeleteTextures(1, &pixmap_priv->tex); if (pixmap_priv->pbo) - glDeleteBuffersARB(1, &pixmap_priv->pbo); + glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; } diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 0a910509c..65e7cfdaa 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -66,25 +66,25 @@ glamor_init_putimage_shaders(ScreenPtr screen) if (!GLEW_ARB_fragment_shader) return; - prog = glCreateProgramObjectARB(); - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, xybitmap_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, xybitmap_fs); - glAttachObjectARB(prog, vs_prog); - glAttachObjectARB(prog, fs_prog); + prog = glCreateProgram(); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xybitmap_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xybitmap_fs); + glAttachShader(prog, vs_prog); + glAttachShader(prog, fs_prog); glamor_link_glsl_prog(prog); - glUseProgramObjectARB(prog); - sampler_uniform_location = glGetUniformLocationARB(prog, "bitmap_sampler"); - glUniform1iARB(sampler_uniform_location, 0); + glUseProgram(prog); + sampler_uniform_location = glGetUniformLocation(prog, "bitmap_sampler"); + glUniform1i(sampler_uniform_location, 0); glamor_priv->put_image_xybitmap_fg_uniform_location = - glGetUniformLocationARB(prog, "fg"); + glGetUniformLocation(prog, "fg"); glamor_priv->put_image_xybitmap_bg_uniform_location = - glGetUniformLocationARB(prog, "bg"); + glGetUniformLocation(prog, "bg"); glamor_get_transform_uniform_locations(prog, &glamor_priv->put_image_xybitmap_transform); glamor_priv->put_image_xybitmap_prog = prog; - glUseProgramObjectARB(0); + glUseProgram(0); } @@ -160,13 +160,13 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; - glUseProgramObjectARB(glamor_priv->put_image_xybitmap_prog); + glUseProgram(glamor_priv->put_image_xybitmap_prog); glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); - glUniform4fvARB(glamor_priv->put_image_xybitmap_fg_uniform_location, + glUniform4fv(glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg); glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); - glUniform4fvARB(glamor_priv->put_image_xybitmap_bg_uniform_location, + glUniform4fv(glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); glGenTextures(1, &tex); @@ -322,7 +322,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glEnable(GL_TEXTURE_2D); assert(GLEW_ARB_fragment_shader); - glUseProgramObjectARB(glamor_priv->finish_access_prog[ax]); + glUseProgram(glamor_priv->finish_access_prog[ax]); x += drawable->x; y += drawable->y; @@ -371,7 +371,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } glDisable(GL_TEXTURE_2D); - glUseProgramObjectARB(0); + glUseProgram(0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index a9015784e..dbb60812f 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -186,7 +186,7 @@ glamor_create_composite_fs(struct shader_key *key) in); - prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); + prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source); free(source); return prog; @@ -223,7 +223,7 @@ glamor_create_composite_vs(struct shader_key *key) mask_coords_setup, main_closing); - prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); + prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, source); free(source); return prog; @@ -243,30 +243,30 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, if (fs == 0) return; - prog = glCreateProgramObjectARB(); - glAttachObjectARB(prog, vs); - glAttachObjectARB(prog, fs); + prog = glCreateProgram(); + glAttachShader(prog, vs); + glAttachShader(prog, fs); glamor_link_glsl_prog(prog); shader->prog = prog; - glUseProgramObjectARB(prog); + glUseProgram(prog); if (key->source == SHADER_SOURCE_SOLID) { - shader->source_uniform_location = glGetUniformLocationARB(prog, + shader->source_uniform_location = glGetUniformLocation(prog, "source"); } else { - source_sampler_uniform_location = glGetUniformLocationARB(prog, + source_sampler_uniform_location = glGetUniformLocation(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, + shader->mask_uniform_location = glGetUniformLocation(prog, "mask"); } else { - mask_sampler_uniform_location = glGetUniformLocationARB(prog, + mask_sampler_uniform_location = glGetUniformLocation(prog, "mask_sampler"); glUniform1i(mask_sampler_uniform_location, 1); } @@ -397,7 +397,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, static void glamor_set_composite_solid(float *color, GLint uniform_location) { - glUniform4fvARB(uniform_location, 1, color); + glUniform4fv(uniform_location, 1, color); } static int @@ -504,7 +504,7 @@ glamor_setup_composite_vbo(ScreenPtr screen) if (glamor_priv->has_mask_coords) glamor_priv->vb_stride += 2 * sizeof(float); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo); + glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); glVertexPointer(2, GL_FLOAT, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset)); glEnableClientState(GL_VERTEX_ARRAY); @@ -559,8 +559,8 @@ glamor_flush_composite_rects(ScreenPtr screen) if (!glamor_priv->render_nr_verts) return; - glBufferDataARB(GL_ARRAY_BUFFER_ARB, glamor_priv->vbo_offset, glamor_priv->vb, - GL_STREAM_DRAW_ARB); + glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, glamor_priv->vb, + GL_STREAM_DRAW); glDrawArrays(GL_QUADS, 0, glamor_priv->render_nr_verts); glamor_reset_composite_vbo(screen); @@ -582,7 +582,7 @@ glamor_emit_composite_rect(ScreenPtr screen, if (glamor_priv->vbo_offset == 0) { if (glamor_priv->vbo == 0) - glGenBuffersARB(1, &glamor_priv->vbo); + glGenBuffers(1, &glamor_priv->vbo); glamor_setup_composite_vbo(screen); } @@ -882,7 +882,7 @@ glamor_composite_with_shader(CARD8 op, goto fail; } - glUseProgramObjectARB(shader->prog); + glUseProgram(shader->prog); if (key.source == SHADER_SOURCE_SOLID) { glamor_set_composite_solid(source_solid_color, shader->source_uniform_location); } else { @@ -1008,7 +1008,7 @@ glamor_composite_with_shader(CARD8 op, } glamor_flush_composite_rects(screen); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(GL_TEXTURE1); @@ -1021,7 +1021,7 @@ glamor_composite_with_shader(CARD8 op, glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); - glUseProgramObjectARB(0); + glUseProgram(0); if (saved_source_format) source->format = saved_source_format; return TRUE; @@ -1031,7 +1031,7 @@ glamor_composite_with_shader(CARD8 op, source->format = saved_source_format; glDisable(GL_BLEND); - glUseProgramObjectARB(0); + glUseProgram(0); return FALSE; } @@ -1223,7 +1223,7 @@ fail: dest->pDrawable->height, glamor_get_picture_location(dest)); - glUseProgramObjectARB(0); + glUseProgram(0); glDisable(GL_BLEND); if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO)) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index a78c30194..436e769f8 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -58,18 +58,18 @@ glamor_init_tile_shader(ScreenPtr screen) if (!GLEW_ARB_fragment_shader) return; - glamor_priv->tile_prog = glCreateProgramObjectARB(); - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, tile_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, tile_fs); - glAttachObjectARB(glamor_priv->tile_prog, vs_prog); - glAttachObjectARB(glamor_priv->tile_prog, fs_prog); + glamor_priv->tile_prog = glCreateProgram(); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, tile_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs); + glAttachShader(glamor_priv->tile_prog, vs_prog); + glAttachShader(glamor_priv->tile_prog, fs_prog); glamor_link_glsl_prog(glamor_priv->tile_prog); sampler_uniform_location = - glGetUniformLocationARB(glamor_priv->tile_prog, "sampler"); - glUseProgramObjectARB(glamor_priv->tile_prog); - glUniform1iARB(sampler_uniform_location, 0); - glUseProgramObjectARB(0); + glGetUniformLocation(glamor_priv->tile_prog, "sampler"); + glUseProgram(glamor_priv->tile_prog); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); } Bool @@ -130,7 +130,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - glUseProgramObjectARB(glamor_priv->tile_prog); + glUseProgram(glamor_priv->tile_prog); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); @@ -169,7 +169,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, } glDisableClientState(GL_VERTEX_ARRAY); - glUseProgramObjectARB(0); + glUseProgram(0); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); return TRUE; From 68c3c6eb0cafd5eb2c208dd76a3a65187256700c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 2 Aug 2011 15:54:15 +0800 Subject: [PATCH 169/462] glamor-es2: Add gles2 option. First commit to enable gles2 support. --enable-glamor-ddx --enable-glamor-gles2 will set thwo MACROs GLAMOR_DDX and GLAMOR_GLES2. Currently, the gles2 support is still incomplete. Signed-off-by: Zhigang Gong --- Makefile.am | 6 +++++- configure.ac | 23 +++++++++++++++++++++++ glamor/glamor_priv.h | 18 ++++++++++++++++++ hw/xfree86/Makefile.am | 8 ++++++-- hw/xfree86/common/xf86pciBus.c | 4 ++++ hw/xfree86/glamor/Makefile.am | 7 +++++-- hw/xfree86/glamor/glamor.c | 7 ++++++- hw/xfree86/glamor/glamor_crtc.c | 18 ++++++++++++++++-- include/xorg-config.h.in | 11 +++++++++++ 9 files changed, 94 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0c701633d..632258eec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,10 @@ if RECORD RECORD_DIR=record endif +if GLAMOR +GLAMOR_DIR=glamor +endif + SUBDIRS = \ doc \ man \ @@ -38,7 +42,7 @@ SUBDIRS = \ $(COMPOSITE_DIR) \ $(GLX_DIR) \ exa \ - glamor \ + $(GLAMOR_DIR) \ config \ hw \ test diff --git a/configure.ac b/configure.ac index caefc4674..73c1bea0e 100644 --- a/configure.ac +++ b/configure.ac @@ -646,6 +646,8 @@ AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest serv AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) +#AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor server (default: no)]), [GLAMOR=$enableval], [GLAMOR=no]) +AC_ARG_ENABLE(glamor-ddx, AS_HELP_STRING([--enable-glamor-ddx], [Build glamor ddx (default: no)]), [GLAMOR_DDX=$enableval], [GLAMOR_DDX=no]) dnl kdrive and its subsystems AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) AC_ARG_ENABLE(xephyr, AS_HELP_STRING([--enable-xephyr], [Build the kdrive Xephyr server (default: auto)]), [XEPHYR=$enableval], [XEPHYR=auto]) @@ -655,6 +657,8 @@ dnl kdrive options AC_ARG_ENABLE(kdrive-kbd, AS_HELP_STRING([--enable-kdrive-kbd], [Build kbd driver for kdrive (default: auto)]), [KDRIVE_KBD=$enableval], [KDRIVE_KBD=auto]) AC_ARG_ENABLE(kdrive-mouse, AC_HELP_STRING([--enable-kdrive-mouse], [Build mouse driver for kdrive (default: auto)]), [KDRIVE_MOUSE=$enableval], [KDRIVE_MOUSE=auto]) AC_ARG_ENABLE(kdrive-evdev, AC_HELP_STRING([--enable-kdrive-evdev], [Build evdev driver for kdrive (default: auto)]), [KDRIVE_EVDEV=$enableval], [KDRIVE_EVDEV=auto]) +dnl glamor options +AC_ARG_ENABLE(glamor-gles2, AS_HELP_STRING([--enable-glamor-gles2], [Build glamor based on gles2 (default: no)]), [GLAMOR_GLES2=$enableval], [GLAMOR_GLES2=no]) dnl chown/chmod to be setuid root as part of build @@ -1765,6 +1769,25 @@ AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) +dnl glamor + +AM_CONDITIONAL([GLAMOR], [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes]) + +GLAMOR=yes + +if test "x$GLAMOR" = xyes; then + AC_DEFINE(GLAMOR,1,[Build Glamor]) + if test "x$GLAMOR_GLES2" = xyes; then + AC_DEFINE(GLAMOR_GLES2,1,[Build glamor over GLES2]) + else + AC_DEFINE(GLAMOR_GL,1,[Build glamor over GL]) + fi + + if test "x$GLAMOR_DDX" = xyes; then + AC_DEFINE(GLAMOR_DDX,1,[Enable glamor ddx driver]) + fi +fi + dnl XWin DDX AC_MSG_CHECKING([whether to build XWin DDX]) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b7fcfbdeb..6005a2cd9 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -29,10 +29,28 @@ #ifdef HAVE_DIX_CONFIG_H #include +#include #endif #include "glamor.h" + +#ifdef GLAMOR_GLES2 + +#define GLEW_ES_ONLY 1 + +#define GL_BGRA GL_BGRA_EXT +#define GL_COLOR_INDEX 0x1900 +#define GL_BITMAP 0x1A00 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 + +#endif + #include #ifdef RENDER diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am index 830f17ac9..f76a36155 100644 --- a/hw/xfree86/Makefile.am +++ b/hw/xfree86/Makefile.am @@ -27,12 +27,16 @@ if INT10MODULE INT10_SUBDIR = int10 endif -SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw glamor os-support parser \ +if GLAMOR +GLAMOR_DIR=glamor +endif + +SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw $(GLAMOR_DIR) os-support parser \ ramdac shadowfb $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \ loader dixmods exa modes \ $(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) doc man -DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw glamor os-support \ +DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw $(GLAMOR_DIR) os-support \ parser ramdac shadowfb vbe vgahw xaa \ loader dixmods dri dri2 exa modes \ utils doc man diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index 56fb62f64..663e70ad9 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1118,7 +1118,11 @@ videoPtrToDriverList(struct pci_device *dev, } else if (dev->device_id == 0x8108) { break; /* "hooray" for poulsbo */ } else { +#if GLAMOR_DDX driverList[0] = "glamor"; +#else + driverList[0] = "intel"; +#endif } break; case 0x102b: driverList[0] = "mga"; break; diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index d691009eb..d9dc8a90a 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -12,8 +12,11 @@ glamor_la_CFLAGS = \ -I$(top_srcdir)/glamor \ -I/usr/include/drm -glamor_la_LDFLAGS = \ - -module -avoid-version -L$(libdir) -lEGL $(top_builddir)/glamor/libglamor.la -lGLEW +glamor_la_LDFLAGS = \ + -module -avoid-version -L$(libdir) -lEGL \ + $(top_builddir)/glamor/libglamor.la \ + -L$(libdir)/../lib64 -lGLEW + glamor_ladir = $(moduledir)/drivers glamor_la_SOURCES = \ glamor.c \ diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 1da7eb20d..a1128da43 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -38,7 +38,13 @@ #define GL_GLEXT_PROTOTYPES #define EGL_EGLEXT_PROTOTYPES #define EGL_DISPLAY_NO_X_MESA + +#if GLAMOR_GLES2 +#include +#else #include +#endif + #include #include @@ -322,7 +328,6 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) glamor->display = eglGetDRMDisplayMESA(glamor->fd); eglBindAPI(EGL_OPENGL_API); - LogMessageVerb(X_INFO, 0, "%s glCreateProgramObjectARB=%p", __FUNCTION__, *(&glCreateProgramObjectARB)); if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index cf4940291..d2f98fb5f 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -53,7 +53,17 @@ #define GL_GLEXT_PROTOTYPES #define EGL_EGLEXT_PROTOTYPES #define EGL_DISPLAY_NO_X_MESA + +#if GLAMOR_GLES2 +#include +#include +#ifndef GL_BGRA +#define GL_BGRA GL_BGRA_EXT +#endif +#else #include +#endif + #include #include @@ -482,11 +492,15 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, drmmode_crtc->cursor); } - - glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); +#if GLAMOR_GLES2 + glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, 64, 64, 0, + GL_BGRA, GL_UNSIGNED_BYTE, image); +#else + glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image); +#endif } diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in index 0d1ea9142..c9760b090 100644 --- a/include/xorg-config.h.in +++ b/include/xorg-config.h.in @@ -139,4 +139,15 @@ /* Build with libdrm support */ #undef WITH_LIBDRM + +/* Build GLAMOR */ +#undef GLAMOR + +/* Build GLAMOR over GLES2*/ +#undef GLAMOR_GLES2 + +/* Build GLAMOR ddx*/ +#undef GLAMOR_DDX + + #endif /* _XORG_CONFIG_H_ */ From 94d884a198b97ed2e78a38ce5a71955bdbf893f8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 3 Aug 2011 10:49:18 +0800 Subject: [PATCH 170/462] glamor-es2: Fix some non-es2 functions. ES2.0 doesn't support QUADS and also doesn't support some EXT APIs. Fix some of them in this commit. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 14 ++++++++------ glamor/glamor_copyarea.c | 8 +++++--- glamor/glamor_core.c | 18 ++++++++++-------- glamor/glamor_pixmap.c | 38 +++++++++++++++++++------------------- glamor/glamor_priv.h | 33 +++++++++++++++++++++++++++++++-- glamor/glamor_render.c | 9 +++++++-- 6 files changed, 80 insertions(+), 40 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index b6789844d..7acfc9853 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -291,9 +291,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) return FALSE; } - glewInit(); #ifndef GLAMOR_GLES2 + glewInit(); if (!GLEW_EXT_framebuffer_object) { ErrorF("GL_EXT_framebuffer_object required\n"); goto fail; @@ -306,17 +306,19 @@ glamor_init(ScreenPtr screen, unsigned int flags) ErrorF("GL_ARB_vertex_shader required\n"); goto fail; } - if (!GLEW_EXT_bgra) { - ErrorF("GL_EXT_bgra required\n"); - goto fail; - } -#endif if (!GLEW_ARB_pixel_buffer_object) { ErrorF("GL_ARB_pixel_buffer_object required\n"); goto fail; } + if (!GLEW_EXT_bgra) { + ErrorF("GL_EXT_bgra required\n"); + goto fail; + } +#endif + + if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, NULL)) { diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index acd1edc8c..4b4a335e0 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -31,6 +31,7 @@ * * GC CopyArea implementation */ +#ifndef GLAMOR_GLES2 static Bool glamor_copy_n_to_n_fbo_blit(DrawablePtr src, DrawablePtr dst, @@ -51,7 +52,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n"); return FALSE; } - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); if (src_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) @@ -77,8 +77,8 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, return FALSE; } glamor_validate_pixmap(dst_pixmap); - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); + glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); 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); src_y_off += dy; @@ -115,6 +115,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, } return TRUE; } +#endif static Bool glamor_copy_n_to_n_textured(DrawablePtr src, @@ -293,13 +294,14 @@ glamor_copy_n_to_n(DrawablePtr src, } /* XXX need revisit to handle overlapped area copying. */ +#ifndef GLAMOR_GLES2 if ((overlaped || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex ) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { goto done; return; } - +#endif glamor_calculate_boxes_bound(&bound, box, nbox); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index d99560fd6..f33762887 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -88,15 +88,15 @@ glamor_compile_glsl_prog(GLenum type, const char *source) prog = glCreateShader(type); glShaderSource(prog, 1, (const GLchar **)&source, NULL); glCompileShader(prog); - glGetObjectParameterivARB(prog, GL_OBJECT_COMPILE_STATUS_ARB, &ok); + glGetShaderiv(prog, GL_COMPILE_STATUS, &ok); if (!ok) { GLchar *info; GLint size; - glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size); + glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); info = malloc(size); - glGetInfoLogARB(prog, size, NULL, info); + glGetShaderInfoLog(prog, size, NULL, info); ErrorF("Failed to compile %s: %s\n", type == GL_FRAGMENT_SHADER ? "FS" : "VS", info); @@ -113,15 +113,15 @@ glamor_link_glsl_prog(GLint prog) GLint ok; glLinkProgram(prog); - glGetObjectParameterivARB(prog, GL_OBJECT_LINK_STATUS_ARB, &ok); + glGetProgramiv(prog, GL_LINK_STATUS, &ok); if (!ok) { GLchar *info; GLint size; - glGetObjectParameterivARB(prog, GL_OBJECT_INFO_LOG_LENGTH_ARB, &size); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); info = malloc(size); - glGetInfoLogARB(prog, size, NULL, info); + glGetProgramInfoLog(prog, size, NULL, info); ErrorF("Failed to link: %s\n", info); FatalError("GLSL link failure\n"); @@ -209,6 +209,7 @@ glamor_finish_access(DrawablePtr drawable) { 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 (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return; @@ -218,8 +219,9 @@ glamor_finish_access(DrawablePtr drawable) } if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { - glBindBuffer (GL_PIXEL_PACK_BUFFER_EXT, 0); - glBindBuffer (GL_PIXEL_UNPACK_BUFFER_EXT, 0); + assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); + glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); pixmap_priv->pbo_valid = FALSE; glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 0f13f09c2..34fc408cc 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -46,7 +46,7 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, vertices[5] = 1; vertices[6] = -1; vertices[7] = 1; - glDrawArrays(GL_QUADS, 0, 4); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); glUseProgram(0); pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; @@ -83,7 +83,7 @@ glamor_validate_pixmap(PixmapPtr pixmap) void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -223,7 +223,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { texels = NULL; - glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, pixmap_priv->pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->pbo); } else texels = pixmap->devPrivate.ptr; @@ -288,7 +288,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, ptexcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); + glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); glGenTextures(1, &tex); @@ -309,7 +309,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &tex); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -347,7 +347,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) if (need_fbo) { if (pixmap_priv->fb == 0) - glGenFramebuffersEXT(1, &pixmap_priv->fb); + glGenFramebuffers(1, &pixmap_priv->fb); glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -355,9 +355,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) pixmap->drawable.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, + glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pixmap_priv->tex, 0); @@ -498,45 +498,45 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glPixelStorei(GL_PACK_INVERT_MESA, 1); if (pixmap_priv->pbo == 0) glGenBuffers (1, &pixmap_priv->pbo); - glBindBuffer (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBufferData (GL_PIXEL_PACK_BUFFER_EXT, + glBindBuffer (GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); + glBufferData (GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, NULL, gl_usage); glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); - data = glMapBuffer (GL_PIXEL_PACK_BUFFER_EXT, gl_access); + data = glMapBuffer (GL_PIXEL_PACK_BUFFER, gl_access); pixmap_priv->pbo_valid = TRUE; if (!glamor_priv->yInverted) glPixelStorei(GL_PACK_INVERT_MESA, 0); - glBindBuffer (GL_PIXEL_PACK_BUFFER_EXT, 0); + glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); } else { data = malloc(stride * pixmap->drawable.height); assert(data); if (access != GLAMOR_ACCESS_WO) { if (pixmap_priv->pbo == 0) glGenBuffers(1, &pixmap_priv->pbo); - glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo); - glBufferData(GL_PIXEL_PACK_BUFFER_EXT, + glBindBuffer(GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); + glBufferData(GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, NULL, GL_STREAM_READ); glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); - read = glMapBuffer(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY); + read = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); for (y = 0; y < pixmap->drawable.height; y++) memcpy(data + y * stride, read + (pixmap->drawable.height - y - 1) * stride, stride); - glUnmapBuffer(GL_PIXEL_PACK_BUFFER_EXT); - glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, 0); + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); pixmap_priv->pbo_valid = FALSE; glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; } } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); done: pixmap->devPrivate.ptr = data; return TRUE; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 6005a2cd9..ac51a729b 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -49,9 +49,31 @@ #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GLEW_ARB_fragment_shader 1 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_CLAMP_TO_BORDER 0x812D + +#define GL_READ_WRITE 0x88BA +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_PACK_ROW_LENGTH 0x0D02 + +#define GLEW_MESA_pack_invert 0 +#define GL_PACK_INVERT_MESA 0x8758 + #endif +#ifdef GLAMOR_GLES2 +#define GL_GLEXT_PROTOTYPES +#include +#include +#else #include +#endif + #ifdef RENDER #include "glyphstr.h" @@ -171,6 +193,12 @@ struct glamor_screen_private; struct glamor_pixmap_private; typedef void (*glamor_pixmap_validate_function_t)(struct glamor_screen_private*, struct glamor_pixmap_private*); + +enum glamor_gl_flavor { + GLAMOR_GL_DESKTOP, // OPENGL API + GLAMOR_GL_ES2 // OPENGL ES2.0 API +}; + #define GLAMOR_CREATE_PIXMAP_CPU 0x100 typedef struct glamor_screen_private { CloseScreenProcPtr saved_close_screen; @@ -196,6 +224,7 @@ typedef struct glamor_screen_private { int vbo_size; char *vb; int vb_stride; + enum glamor_gl_flavor gl_flavor; /* glamor_finishaccess */ GLint finish_access_prog[2]; @@ -287,8 +316,8 @@ typedef struct glamor_pixmap_private { #define GLAMOR_CHECK_PENDING_FILL(_glamor_priv_, _pixmap_priv_) do \ { \ if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ - glUseProgramObjectARB(_glamor_priv_->solid_prog); \ - glUniform4fvARB(_glamor_priv_->solid_color_uniform_location, 1, \ + glUseProgram(_glamor_priv_->solid_prog); \ + glUniform4fv(_glamor_priv_->solid_color_uniform_location, 1, \ _pixmap_priv_->pending_op.fill.color4fv); \ } \ } while(0) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index dbb60812f..224ae27cc 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -362,6 +362,9 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); switch (picture->repeatType) { case RepeatNone: +#ifdef GLAMOR_GLES2 + assert(0); +#endif 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; @@ -562,7 +565,7 @@ glamor_flush_composite_rects(ScreenPtr screen) glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, glamor_priv->vb, GL_STREAM_DRAW); - glDrawArrays(GL_QUADS, 0, glamor_priv->render_nr_verts); + glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts); glamor_reset_composite_vbo(screen); } @@ -574,7 +577,7 @@ glamor_emit_composite_rect(ScreenPtr screen, { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > + if (glamor_priv->vbo_offset + 6 * glamor_priv->vb_stride > glamor_priv->vbo_size) { glamor_flush_composite_rects(screen); @@ -590,6 +593,8 @@ glamor_emit_composite_rect(ScreenPtr 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, 0); + glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 2); glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 3); } From ee33c947aac10b2b1ec2c5b070fbd81cef1773c6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 3 Aug 2011 16:52:19 +0800 Subject: [PATCH 171/462] glamor-es: Use glVertexAttribPointer to replace glVertexPointer. As GLES2 doesn't support glVertexPointer. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 34 +++++++++++++++++---- glamor/glamor_core.c | 65 ++++++++++++++++++++++++++++++++++++++++ glamor/glamor_fill.c | 30 +++++++++++++++++-- glamor/glamor_pixmap.c | 41 +++++++++++++++++++++++-- glamor/glamor_priv.h | 8 ++++- glamor/glamor_putimage.c | 28 +++++++++++++++-- glamor/glamor_render.c | 63 ++++++++++++++++++++++++++++++++------ glamor/glamor_tile.c | 46 ++++++++++++++++++++++++++-- 8 files changed, 291 insertions(+), 24 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 4b4a335e0..7a84adbf2 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -176,29 +176,46 @@ glamor_copy_n_to_n_textured(DrawablePtr src, pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); + +#if 0 glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); dx += src_x_off; dy += src_y_off; pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - +#if 0 glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glUseProgram(glamor_priv->finish_access_prog[0]); - } +#else + + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + texcoords); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glUseProgram(glamor_priv->finish_access_prog[2]); +#endif + + } else { GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); } @@ -223,13 +240,20 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - glUseProgram(0); - +#if 0 glDisableClientState(GL_VERTEX_ARRAY); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } +#else + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glDisable(GL_TEXTURE_2D); + } +#endif + glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ if (flush_needed) glFlush(); diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f33762887..f585d6a2e 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -162,11 +162,42 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "{\n" " gl_FragColor = vec4(texture2D(sampler, gl_TexCoord[0].xy).rgb, 1);\n" "}\n"; + const char *es_vs_source = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "varying vec2 source_texture;\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord0.xy;\n" + "}\n"; + + const char *es_fs_source = + "varying vec2 source_texture;\n" + "uniform sampler2D sampler;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(sampler, source_texture);\n" + "}\n"; + + const char *es_aswizzle_source = + "varying vec2 source_texture;\n" + "varying vec2 texcoords;\n" + "uniform sampler2D sampler;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" + "}\n"; + + GLint fs_prog, vs_prog, avs_prog, aswizzle_prog; + GLint es_fs_prog, es_vs_prog, es_avs_prog, es_aswizzle_prog; glamor_priv->finish_access_prog[0] = glCreateProgram(); glamor_priv->finish_access_prog[1] = glCreateProgram(); + glamor_priv->finish_access_prog[2] = glCreateProgram(); + glamor_priv->finish_access_prog[3] = glCreateProgram(); if (GLEW_ARB_fragment_shader) { vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); @@ -178,15 +209,36 @@ glamor_init_finish_access_shaders(ScreenPtr screen) aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, aswizzle_source); glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); glAttachShader(glamor_priv->finish_access_prog[1], aswizzle_prog); + + es_vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); + es_fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_fs_source); + glAttachShader(glamor_priv->finish_access_prog[2], es_vs_prog); + glAttachShader(glamor_priv->finish_access_prog[2], es_fs_prog); + + es_avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); + es_aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_aswizzle_source); + glAttachShader(glamor_priv->finish_access_prog[3], es_avs_prog); + glAttachShader(glamor_priv->finish_access_prog[3], es_aswizzle_prog); + } else { vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); ErrorF("Lack of framgment shader support.\n"); } + + glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]); glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]); + glBindAttribLocation(glamor_priv->finish_access_prog[2], GLAMOR_VERTEX_POS, "v_position"); + glBindAttribLocation(glamor_priv->finish_access_prog[2], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glamor_link_glsl_prog(glamor_priv->finish_access_prog[2]); + + glBindAttribLocation(glamor_priv->finish_access_prog[3], GLAMOR_VERTEX_POS, "v_position"); + glBindAttribLocation(glamor_priv->finish_access_prog[3], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glamor_link_glsl_prog(glamor_priv->finish_access_prog[3]); + if (GLEW_ARB_fragment_shader) { GLint sampler_uniform_location; @@ -201,6 +253,19 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glUseProgram(glamor_priv->finish_access_prog[1]); glUniform1i(sampler_uniform_location, 0); glUseProgram(0); + + sampler_uniform_location = + glGetUniformLocation(glamor_priv->finish_access_prog[2], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[2]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); + + sampler_uniform_location = + glGetUniformLocation(glamor_priv->finish_access_prog[3], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[3]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); + } } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 14cce0c8c..bfa30b2e3 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -103,16 +103,32 @@ glamor_init_solid_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); const char *solid_vs_only = +#if 0 +#else + "attribute vec4 v_position;" +#endif "uniform vec4 color;\n" "void main()\n" "{\n" +#if 0 " gl_Position = gl_Vertex;\n" +#else + " gl_Position = v_position;\n" +#endif " gl_Color = color;\n" "}\n"; const char *solid_vs = +#if 0 +#else + "attribute vec4 v_position;" +#endif "void main()\n" "{\n" +#if 0 " gl_Position = gl_Vertex;\n" +#else + " gl_Position = v_position;\n" +#endif "}\n"; const char *solid_fs = "uniform vec4 color;\n" @@ -132,6 +148,8 @@ glamor_init_solid_shader(ScreenPtr screen) vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs_only); glAttachShader(glamor_priv->solid_prog, vs_prog); } + + glBindAttribLocation(glamor_priv->solid_prog, GLAMOR_VERTEX_POS, "v_position"); glamor_link_glsl_prog(glamor_priv->solid_prog); glamor_priv->solid_color_uniform_location = @@ -188,17 +206,25 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); +#if 0 glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - +#if 0 glDisableClientState(GL_VERTEX_ARRAY); +#else + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif glUseProgram(0); return TRUE; fail: diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 34fc408cc..ce4ca0097 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -32,9 +32,14 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, glamor_pixmap_private *pixmap_priv) { GLfloat vertices[8]; -// glamor_set_destination_pixmap_priv_nc(pixmap_priv); +#if 0 glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif glUseProgram(glamor_priv->solid_prog); glUniform4fv(glamor_priv->solid_color_uniform_location, 1, pixmap_priv->pending_op.fill.color4fv); @@ -47,7 +52,11 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, vertices[6] = -1; vertices[7] = 1; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +#if 0 glDisableClientState(GL_VERTEX_ARRAY); +#else + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif glUseProgram(0); pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } @@ -84,8 +93,10 @@ void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); +#ifndef GLAMOR_GLES2 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); +#endif glViewport(0, 0, pixmap_priv->container->drawable.width, @@ -129,6 +140,7 @@ glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) void glamor_set_alu(unsigned char alu) { +#ifndef GLAMOR_GLES2 if (alu == GXcopy) { glDisable(GL_COLOR_LOGIC_OP); return; @@ -183,6 +195,10 @@ glamor_set_alu(unsigned char alu) default: FatalError("unknown logic op\n"); } +#else + if (alu != GXcopy) + ErrorF("unsupported alu %x \n", alu); +#endif } @@ -219,8 +235,9 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +#ifndef GLAMOR_GLES2 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - +#endif if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { texels = NULL; glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->pbo); @@ -282,12 +299,23 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i ptexcoords = texcoords_inv; /* Slow path, we need to flip y or wire alpha to 1. */ +#if 0 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); +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + ptexcoords); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#endif glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); @@ -300,14 +328,23 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); +#if 0 glUseProgram(glamor_priv->finish_access_prog[ax]); +#else + glUseProgram(glamor_priv->finish_access_prog[ax + 2]); +#endif glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisable(GL_TEXTURE_2D); glUseProgram(0); +#if 0 glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#else + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#endif glDeleteTextures(1, &tex); glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index ac51a729b..217600844 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -166,6 +166,12 @@ typedef struct { #define GLAMOR_NUM_GLYPH_CACHES 4 +enum glamor_vertex_type { + GLAMOR_VERTEX_POS, + GLAMOR_VERTEX_SOURCE, + GLAMOR_VERTEX_MASK +}; + enum shader_source { SHADER_SOURCE_SOLID, SHADER_SOURCE_TEXTURE, @@ -227,7 +233,7 @@ typedef struct glamor_screen_private { enum glamor_gl_flavor gl_flavor; /* glamor_finishaccess */ - GLint finish_access_prog[2]; + GLint finish_access_prog[4]; /* glamor_solid */ GLint solid_prog; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 65e7cfdaa..4b2215a9f 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -298,17 +298,30 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, /* XXX consider to reuse a function to do the following work. */ glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); +#if 0 glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + texcoords); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#endif glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +#ifndef GLAMOR_GLES2 glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / pixmap->drawable.bitsPerPixel); +#endif glGenTextures(1, &tex); @@ -321,8 +334,11 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); - assert(GLEW_ARB_fragment_shader); +#if 0 glUseProgram(glamor_priv->finish_access_prog[ax]); +#else + glUseProgram(glamor_priv->finish_access_prog[ax + 2]); +#endif x += drawable->x; y += drawable->y; @@ -372,11 +388,17 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glDisable(GL_TEXTURE_2D); glUseProgram(0); +#if 0 glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#else + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#endif glDeleteTextures(1, &tex); +#ifndef GLAMOR_GLES2 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); +#endif glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); return; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 224ae27cc..6b8c7601b 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -36,7 +36,7 @@ #include "mipict.h" #include "fbpict.h" -#include "glu3/glu3.h" +//#include "glu3/glu3.h" struct shader_key { enum shader_source source; @@ -77,16 +77,18 @@ glamor_create_composite_fs(struct shader_key *key) " return source;\n" "}\n"; const char *source_alpha_pixmap_fetch = + "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" "{\n" - " return texture2D(source_sampler, gl_TexCoord[0].xy);\n" + " return texture2D(source_sampler, source_texture);\n" "}\n"; const char *source_pixmap_fetch = + "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" "{\n" - " return vec4(texture2D(source_sampler, gl_TexCoord[0].xy).rgb, 1);\n" + " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" "}\n"; const char *mask_solid_fetch = "uniform vec4 mask;\n" @@ -95,16 +97,18 @@ glamor_create_composite_fs(struct shader_key *key) " return mask;\n" "}\n"; const char *mask_alpha_pixmap_fetch = + "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" - " return texture2D(mask_sampler, gl_TexCoord[1].xy);\n" + " return texture2D(mask_sampler, mask_texture);\n" "}\n"; const char *mask_pixmap_fetch = + "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" - " return vec4(texture2D(mask_sampler, gl_TexCoord[1].xy).rgb, 1);\n" + " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" "}\n"; const char *in_source_only = "void main()\n" @@ -196,13 +200,18 @@ static GLuint glamor_create_composite_vs(struct shader_key *key) { const char *main_opening = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "attribute vec4 v_texcoord1;\n" + "varying vec2 source_texture;\n" + "varying vec2 mask_texture;\n" "void main()\n" "{\n" - " gl_Position = gl_Vertex;\n"; + " gl_Position = v_position;\n"; const char *source_coords = - " gl_TexCoord[0] = gl_MultiTexCoord0;\n"; + " source_texture = v_texcoord0.xy;\n"; const char *mask_coords = - " gl_TexCoord[1] = gl_MultiTexCoord1;\n"; + " mask_texture = v_texcoord1.xy;\n"; const char *main_closing = "}\n"; const char *source_coords_setup = ""; @@ -246,6 +255,11 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, prog = glCreateProgram(); glAttachShader(prog, vs); glAttachShader(prog, fs); + + glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position"); + glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); + glamor_link_glsl_prog(prog); shader->prog = prog; @@ -508,24 +522,48 @@ glamor_setup_composite_vbo(ScreenPtr screen) glamor_priv->vb_stride += 2 * sizeof(float); glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + +#if 0 glVertexPointer(2, GL_FLOAT, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset)); glEnableClientState(GL_VERTEX_ARRAY); +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, + (void *)((long)glamor_priv->vbo_offset)); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif if (glamor_priv->has_source_coords) { +#if 0 glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, glamor_priv->vb_stride, (void *)(glamor_priv->vbo_offset + 2 * sizeof(float))); glEnableClientState(GL_TEXTURE_COORD_ARRAY); +#else + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, + (void *)((long)glamor_priv->vbo_offset + 2 * sizeof(float))); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#endif } if (glamor_priv->has_mask_coords) { +#if 0 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); +#else + glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, + (void *)((long)glamor_priv->vbo_offset + + (glamor_priv->has_source_coords ? 4 : 2) * + sizeof(float))); + glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); +#endif } } @@ -888,6 +926,8 @@ glamor_composite_with_shader(CARD8 op, } glUseProgram(shader->prog); + + if (key.source == SHADER_SOURCE_SOLID) { glamor_set_composite_solid(source_solid_color, shader->source_uniform_location); } else { @@ -1014,12 +1054,17 @@ glamor_composite_with_shader(CARD8 op, glamor_flush_composite_rects(screen); glBindBuffer(GL_ARRAY_BUFFER, 0); +#if 0 glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTexture(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - +#else + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); +#endif REGION_UNINIT(dst->pDrawable->pScreen, ®ion); glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 436e769f8..cdb0611c6 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -41,16 +41,35 @@ glamor_init_tile_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); const char *tile_vs = +#if 0 +#else + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "varying vec2 tile_texture;\n" +#endif "void main()\n" "{\n" +#if 0 " gl_Position = gl_Vertex;\n" " gl_TexCoord[0] = gl_MultiTexCoord0;\n" +#else + " gl_Position = v_position;\n" + " tile_texture = v_texcoord0.xy;\n" +#endif "}\n"; const char *tile_fs = +#if 0 +#else + "varying vec2 tile_texture;\n" +#endif "uniform sampler2D sampler;\n" "void main()\n" "{\n" +#if 0 " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" +#else + " gl_FragColor = texture2D(sampler, tile_texture);\n" +#endif "}\n"; GLint fs_prog, vs_prog; GLint sampler_uniform_location; @@ -63,6 +82,9 @@ glamor_init_tile_shader(ScreenPtr screen) fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs); glAttachShader(glamor_priv->tile_prog, vs_prog); glAttachShader(glamor_priv->tile_prog, fs_prog); + + glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_POS, "v_position"); + glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glamor_link_glsl_prog(glamor_priv->tile_prog); sampler_uniform_location = @@ -144,9 +166,16 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords); +#if 0 glClientActiveTexture(GL_TEXTURE0); glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); +#else + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + source_texcoords); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#endif } else { GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); @@ -157,18 +186,31 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_priv->yInverted, vertices); +#if 0 glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); glEnableClientState(GL_VERTEX_ARRAY); - +#else + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +#if 0 if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glClientActiveTexture(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } glDisableClientState(GL_VERTEX_ARRAY); - +#else + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glDisable(GL_TEXTURE_2D); + } + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); +#endif glUseProgram(0); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); From 29e358f6b3838a56b53ec809665f2e7be1731722 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 9 Aug 2011 09:59:08 -0400 Subject: [PATCH 172/462] glamor: Fix one typo error in README. Signed-off-by: Zhigang Gong --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 05effbeba..fd31d9936 100644 --- a/README +++ b/README @@ -14,7 +14,7 @@ diff -ur ../Downloads/glew-1.5.8/Makefile glew-1.5.8/Makefile endif -INCLUDE = -Iinclude + -+NCLUDE = -Iinclude ++INCLUDE = -Iinclude CFLAGS = $(OPT) $(WARN) $(INCLUDE) $(CFLAGS.EXTRA) +ifeq ($(NO_GLX), 1) +CFLAGS += -D_NO_GLX_ From 36a93f62c7830af088a54514eab6bf4d92423df6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 9 Aug 2011 09:59:56 -0400 Subject: [PATCH 173/462] glamor_gles2: Use gl_flavor to determine which version of GL. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 6 ++++++ glamor/glamor_pixmap.c | 48 +++++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 7acfc9853..eeb85f23a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -379,6 +379,12 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_glyphs_init(screen); glamor_pixmap_init(screen); +#ifdef GLAMOR_GLES2 + glamor_priv->gl_flavor = GLAMOR_GL_ES2; +#else + glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; +#endif + return TRUE; fail: diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index ce4ca0097..5dd59756d 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -213,6 +213,7 @@ 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); + glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); unsigned int stride, row_length; void *texels; GLenum iformat; @@ -229,15 +230,24 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, break; } + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + iformat = format; + type = GL_UNSIGNED_BYTE; + } stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; glBindTexture(GL_TEXTURE_2D, tex); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -#ifndef GLAMOR_GLES2 - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); -#endif + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + } + else { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } + if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { texels = NULL; glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->pbo); @@ -524,15 +534,26 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) ErrorF("Glamor: Invalid access code. %d\n", access); assert(0); } - + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + data = malloc(stride * pixmap->drawable.height); row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + } + else { + glPixelStorei(GL_PACK_ALIGNMENT, 4); + // glPixelStorei(GL_PACK_ROW_LENGTH, 0); + } if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { - if (!glamor_priv->yInverted) + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); glPixelStorei(GL_PACK_INVERT_MESA, 1); + } + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { if (pixmap_priv->pbo == 0) glGenBuffers (1, &pixmap_priv->pbo); glBindBuffer (GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); @@ -545,9 +566,16 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) data = glMapBuffer (GL_PIXEL_PACK_BUFFER, gl_access); pixmap_priv->pbo_valid = TRUE; - if (!glamor_priv->yInverted) + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); glPixelStorei(GL_PACK_INVERT_MESA, 0); + } glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); + } else { + glReadPixels (0, 0, + row_length, pixmap->drawable.height, + format, type, data); + } } else { data = malloc(stride * pixmap->drawable.height); assert(data); @@ -588,7 +616,7 @@ _glamor_destroy_upload_pixmap(PixmapPtr pixmap) assert(pixmap_priv->gl_fbo == 0); if (pixmap_priv->fb) - glDeleteFramebuffersEXT(1, &pixmap_priv->fb); + glDeleteFramebuffers(1, &pixmap_priv->fb); if (pixmap_priv->tex) glDeleteTextures(1, &pixmap_priv->tex); if (pixmap_priv->pbo) From 7aecfa245facf754ff8e09d6ef1ad0ab802156fc Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 9 Aug 2011 10:01:39 -0400 Subject: [PATCH 174/462] glamor-es2: Add --enable-glamor-gles2 to build system. Now, to build a gles2 version of glamor server, we could use ./autogen.sh --enable-glamor-ddx --enable-glamor-gles2 Signed-off-by: Zhigang Gong --- configure.ac | 2 ++ glamor/Makefile.am | 6 +++++- glamor/glamor_core.c | 17 +++++++++++------ glamor/glamor_priv.h | 6 ++++++ glamor/glamor_putimage.c | 33 ++++++++++++++++++++++----------- glamor/glamor_render.c | 2 +- glamor/glamor_setspans.c | 2 ++ hw/xfree86/common/Makefile.am | 8 +++++++- hw/xfree86/common/xf86pciBus.c | 2 +- hw/xfree86/glamor/Makefile.am | 9 ++++++++- hw/xfree86/glamor/glamor.c | 13 ++++++++++++- hw/xfree86/glamor/glamor_crtc.c | 3 ++- 12 files changed, 79 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 73c1bea0e..a94cd009a 100644 --- a/configure.ac +++ b/configure.ac @@ -1772,6 +1772,8 @@ AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) dnl glamor AM_CONDITIONAL([GLAMOR], [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes]) +AM_CONDITIONAL([GLAMOR_GLES2], [test "x$GLAMOR_GLES2" = xyes]) +AM_CONDITIONAL([GLAMOR_DDX], [test "x$GLAMOR_DDX" = xyes]) GLAMOR=yes diff --git a/glamor/Makefile.am b/glamor/Makefile.am index e2678f060..97b677a8a 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -10,10 +10,14 @@ if XORG sdk_HEADERS = glamor.h endif +if GLAMOR_GLES2 +GLAMOR_GLES2_CFLAGS = -DGLAMOR_GLES2 +endif + INCLUDES = \ $(XORG_INCS) -AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) +AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(GLAMOR_GLES2_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f585d6a2e..096e40b20 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -141,6 +141,7 @@ void glamor_init_finish_access_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); +#ifndef GLAMOR_GLES2 const char *vs_source = "void main()\n" "{\n" @@ -154,7 +155,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "{\n" " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" "}\n"; - + const char *aswizzle_source = "varying vec2 texcoords;\n" "uniform sampler2D sampler;\n" @@ -162,6 +163,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "{\n" " gl_FragColor = vec4(texture2D(sampler, gl_TexCoord[0].xy).rgb, 1);\n" "}\n"; +#endif const char *es_vs_source = "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" @@ -200,6 +202,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glamor_priv->finish_access_prog[3] = glCreateProgram(); if (GLEW_ARB_fragment_shader) { +#ifndef GLAMOR_GLES2 vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source); glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); @@ -209,7 +212,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, aswizzle_source); glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); glAttachShader(glamor_priv->finish_access_prog[1], aswizzle_prog); - +#endif es_vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); es_fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_fs_source); glAttachShader(glamor_priv->finish_access_prog[2], es_vs_prog); @@ -221,16 +224,18 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glAttachShader(glamor_priv->finish_access_prog[3], es_aswizzle_prog); } else { +#ifndef GLAMOR_GLES2 vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); ErrorF("Lack of framgment shader support.\n"); +#endif } - +#ifndef GLAMOR_GLES2 glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]); glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]); - +#endif glBindAttribLocation(glamor_priv->finish_access_prog[2], GLAMOR_VERTEX_POS, "v_position"); glBindAttribLocation(glamor_priv->finish_access_prog[2], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glamor_link_glsl_prog(glamor_priv->finish_access_prog[2]); @@ -241,7 +246,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) if (GLEW_ARB_fragment_shader) { GLint sampler_uniform_location; - +#ifndef GLAMOR_GLES2 sampler_uniform_location = glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); glUseProgram(glamor_priv->finish_access_prog[0]); @@ -253,7 +258,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glUseProgram(glamor_priv->finish_access_prog[1]); glUniform1i(sampler_uniform_location, 0); glUseProgram(0); - +#endif sampler_uniform_location = glGetUniformLocation(glamor_priv->finish_access_prog[2], "sampler"); glUseProgram(glamor_priv->finish_access_prog[2]); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 217600844..c04e118ed 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -60,10 +60,16 @@ #define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_READ 0x88E1 #define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 #define GLEW_MESA_pack_invert 0 #define GL_PACK_INVERT_MESA 0x8758 +#define glMapBuffer(x, y) NULL +#define glUnmapBuffer(x) +#define glRasterPos2i(x,y) +#define glDrawPixels(x,y,z,a,b) + #endif #ifdef GLAMOR_GLES2 diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 4b2215a9f..a6aadce11 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -36,6 +36,7 @@ void glamor_init_putimage_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); +#if 0 const char *xybitmap_vs = "uniform float x_bias;\n" "uniform float x_scale;\n" @@ -85,6 +86,7 @@ glamor_init_putimage_shaders(ScreenPtr screen) &glamor_priv->put_image_xybitmap_transform); glamor_priv->put_image_xybitmap_prog = prog; glUseProgram(0); +#endif } @@ -254,7 +256,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_get_screen_private(drawable->pScreen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - GLenum type, format; + GLenum type, format, iformat; RegionPtr clip; BoxPtr pbox; int nbox; @@ -317,17 +319,27 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #endif - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -#ifndef GLAMOR_GLES2 - glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / - pixmap->drawable.bitsPerPixel); -#endif - + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / + pixmap->drawable.bitsPerPixel); + } + else { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +// glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } glGenTextures(1, &tex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + type = GL_UNSIGNED_BYTE; + iformat = format; + } + else { + iformat = GL_RGBA; + } + glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -396,9 +408,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #endif glDeleteTextures(1, &tex); -#ifndef GLAMOR_GLES2 - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); -#endif + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); return; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6b8c7601b..0567f6717 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -377,7 +377,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, switch (picture->repeatType) { case RepeatNone: #ifdef GLAMOR_GLES2 - assert(0); + assert(1); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 14a24378f..af2664301 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -43,6 +43,8 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, BoxRec *pbox; int x_off, y_off; + goto fail; + if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, &format, &type, diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am index c031d4be3..173d76570 100644 --- a/hw/xfree86/common/Makefile.am +++ b/hw/xfree86/common/Makefile.am @@ -89,4 +89,10 @@ if LNXACPI XORG_CFLAGS += -DHAVE_ACPI endif -AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) +if GLAMOR_DDX +GLAMOR_DDX_CFLAGS = -DGLAMOR_DDX +endif + +AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_DDX_CFLAGS) + + diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index 663e70ad9..7ab3f2875 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1118,7 +1118,7 @@ videoPtrToDriverList(struct pci_device *dev, } else if (dev->device_id == 0x8108) { break; /* "hooray" for poulsbo */ } else { -#if GLAMOR_DDX +#ifdef GLAMOR_DDX driverList[0] = "glamor"; #else driverList[0] = "intel"; diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index d9dc8a90a..71d491441 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -12,10 +12,17 @@ glamor_la_CFLAGS = \ -I$(top_srcdir)/glamor \ -I/usr/include/drm +if GLAMOR_GLES2 +glamor_la_CFLAGS+=-DGLAMOR_GLES2 +GLAMOR_GL_LIB = -lGLESv2 +else +GLAMOR_GL_LIB = -L$(libdir)/../lib64 -lGLEW +endif + glamor_la_LDFLAGS = \ -module -avoid-version -L$(libdir) -lEGL \ $(top_builddir)/glamor/libglamor.la \ - -L$(libdir)/../lib64 -lGLEW + -L$(libdir)/../lib64 $(GLAMOR_GL_LIB) glamor_ladir = $(moduledir)/drivers glamor_la_SOURCES = \ diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index a1128da43..82ebeeb52 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -306,6 +306,13 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); const char *version; VisualPtr visual; + EGLint config_attribs[] = { +#ifdef GLAMOR_GLES2 + EGL_CONTEXT_CLIENT_VERSION, 2, +#endif + EGL_NONE + }; + /* If serverGeneration != 1 then fd was closed during the last time closing screen, actually in eglTerminate(). */ @@ -327,7 +334,11 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) glamor->display = eglGetDRMDisplayMESA(glamor->fd); +#ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); +#else + eglBindAPI(EGL_OPENGL_ES_API); +#endif if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); @@ -338,7 +349,7 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) xf86Msg(X_INFO, "%s: EGL version %s:", glamor_name, version); glamor->context = eglCreateContext(glamor->display, - NULL, EGL_NO_CONTEXT, NULL); + NULL, EGL_NO_CONTEXT, config_attribs); if (glamor->context == EGL_NO_CONTEXT) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n"); diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index d2f98fb5f..5c2b5c124 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -493,7 +493,8 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, drmmode_crtc->cursor); } glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); -#if GLAMOR_GLES2 +#ifdef GLAMOR_GLES2 + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, 64, 64, 0, GL_BGRA, GL_UNSIGNED_BYTE, image); #else From 41b13fbd264594f88905b1cf8dcb2f14e7ee5b69 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 10 Aug 2011 01:42:26 -0700 Subject: [PATCH 175/462] glamor: Use function pointer to get extenstion calls This is the formal usage for extension functions. --- hw/xfree86/glamor/glamor.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 82ebeeb52..e7ee95631 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -45,6 +45,7 @@ #include #endif +#define MESA_EGL_NO_X11_HEADERS #include #include @@ -79,6 +80,10 @@ struct glamor_screen_private { CloseScreenProcPtr CloseScreen; int fd; int cpp; + + PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; + PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; + }; static inline struct glamor_screen_private * @@ -109,7 +114,7 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) attribs[1] = width; attribs[3] = height; - image = eglCreateDRMImageMESA(glamor->display, attribs); + image = (glamor->egl_create_drm_image_mesa)(glamor->display, attribs); if (image == EGL_NO_IMAGE_KHR) return FALSE; @@ -131,7 +136,7 @@ glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) { struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); EGLint name; - eglExportDRMImageMESA (glamor->display, glamor->root, &name, (EGLint*) handle, (EGLint*) pitch); + (glamor->egl_export_drm_image_mesa)(glamor->display, glamor->root, &name, (EGLint*) handle, (EGLint*) pitch); } EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) @@ -148,7 +153,7 @@ EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) attribs[1] = width; attribs[3] = height; - return eglCreateDRMImageMESA(glamor->display, attribs); + return (glamor->egl_create_drm_image_mesa)(glamor->display, attribs); } void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor) @@ -162,7 +167,7 @@ glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uin { struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); EGLint name; - eglExportDRMImageMESA (glamor->display, cursor, &name, (EGLint*) handle, (EGLint*) pitch); + (glamor->egl_export_drm_image_mesa)(glamor->display, cursor, &name, (EGLint*) handle, (EGLint*) pitch); ErrorF("cursor stride: %d\n", *pitch); } @@ -346,7 +351,16 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) } version = eglQueryString(glamor->display, EGL_VERSION); - xf86Msg(X_INFO, "%s: EGL version %s:", glamor_name, version); + xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); + + glamor->egl_create_drm_image_mesa = eglGetProcAddress("eglCreateDRMImageMESA"); + glamor->egl_export_drm_image_mesa = eglGetProcAddress("eglExportDRMImageMESA"); + + if (!glamor->egl_create_drm_image_mesa || !glamor->egl_export_drm_image_mesa) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "eglGetProcAddress() failed\n"); + return FALSE; + } glamor->context = eglCreateContext(glamor->display, NULL, EGL_NO_CONTEXT, config_attribs); From b2bff334ce4f36352497f1c1d4e9f0e5b3336136 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 9 Aug 2011 19:37:17 -0700 Subject: [PATCH 176/462] glamor: Require libdrm CFLAGS for building Need to depend on libdrm CFLAGS for glamor building. --- glamor/Makefile.am | 2 +- hw/xfree86/glamor/Makefile.am | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 97b677a8a..2df76bd53 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -17,7 +17,7 @@ endif INCLUDES = \ $(XORG_INCS) -AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(GLAMOR_GLES2_CFLAGS) +AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(GLAMOR_GLES2_CFLAGS) $(LIBDRM_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index 71d491441..a00f08ac5 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -1,7 +1,7 @@ glamor_la_LTLIBRARIES = glamor.la glamor_la_CFLAGS = \ -DHAVE_XORG_CONFIG_H \ - @DIX_CFLAGS@ @XORG_CFLAGS@ \ + @DIX_CFLAGS@ @XORG_CFLAGS@ @LIBDRM_CFLAGS@ \ -I$(top_srcdir)/hw/xfree86/common \ -I$(top_srcdir)/hw/xfree86/os-support/bus \ -I$(top_srcdir)/hw/xfree86/parser \ @@ -9,8 +9,7 @@ glamor_la_CFLAGS = \ -I$(top_srcdir)/hw/xfree86/ddc \ -I$(top_srcdir)/hw/xfree86/ramdac \ -I$(top_srcdir)/hw/xfree86/i2c \ - -I$(top_srcdir)/glamor \ - -I/usr/include/drm + -I$(top_srcdir)/glamor if GLAMOR_GLES2 glamor_la_CFLAGS+=-DGLAMOR_GLES2 From d66bd9714e1e1af4267fb4eb208143a070e65ee3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 09:54:28 -0400 Subject: [PATCH 177/462] glamor: Concentrate FBO's creation to one function. And add status checking for it. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 9 +-------- glamor/glamor_pixmap.c | 43 +++++++++++++++++++++++++++++++++--------- glamor/glamor_priv.h | 14 ++++++++++++++ 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index eeb85f23a..dd0d69db7 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -74,14 +74,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) */ pixmap_priv->gl_fbo = 1; pixmap_priv->gl_tex = 1; - glGenFramebuffers(1, &pixmap_priv->fb); - glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - pixmap_priv->tex, - 0); - + glamor_pixmap_ensure_fb(pixmap); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 5dd59756d..d747ade43 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -359,6 +359,39 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void +glamor_pixmap_ensure_fb(PixmapPtr pixmap) +{ + int status; + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv->fb == 0) + glGenFramebuffers(1, &pixmap_priv->fb); + assert(pixmap_priv->tex != 0); + glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + pixmap_priv->tex, + 0); + status = glCheckFramebufferStatus (GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + const char *str; + switch (status) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break; + case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break; + default: str = "unknown error"; break; + } + + LogMessageVerb(X_INFO, 0, + "destination is framebuffer incomplete: %s [%#x]\n", + str, status); + assert(0); + } +} /* * Prepare to upload a pixmap to texture memory. @@ -393,21 +426,13 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) glGenTextures(1, &pixmap_priv->tex); if (need_fbo) { - if (pixmap_priv->fb == 0) - glGenFramebuffers(1, &pixmap_priv->fb); glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); 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); - - glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - pixmap_priv->tex, - 0); + glamor_pixmap_ensure_fb(pixmap); } return 0; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index c04e118ed..bf032b1cb 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -62,6 +62,10 @@ #define GL_PACK_ROW_LENGTH 0x0D02 #define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 + #define GLEW_MESA_pack_invert 0 #define GL_PACK_INVERT_MESA 0x8758 @@ -802,6 +806,16 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access); **/ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap); +/** + * Ensure to have a fbo attached to the pixmap. + * If the pixmap already has one fbo then do nothing. + * Otherwise, it will generate a new fbo, and bind + * the pixmap's texture to the fbo. + * The pixmap must has a valid texture before call this + * API, othersie, it will trigger a assert. + */ +void +glamor_pixmap_ensure_fb(PixmapPtr pixmap); /** * Upload a pixmap to gl texture. Used by dynamic pixmap From 2146a25bac4392c47ef06ecddbf12db184926b7e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 15:03:48 -0400 Subject: [PATCH 178/462] glamor-ddx: Silence one warning. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index e7ee95631..317342b13 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -353,8 +353,8 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) version = eglQueryString(glamor->display, EGL_VERSION); xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); - glamor->egl_create_drm_image_mesa = eglGetProcAddress("eglCreateDRMImageMESA"); - glamor->egl_export_drm_image_mesa = eglGetProcAddress("eglExportDRMImageMESA"); + glamor->egl_create_drm_image_mesa = (PFNEGLCREATEDRMIMAGEMESA)eglGetProcAddress("eglCreateDRMImageMESA"); + glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA)eglGetProcAddress("eglExportDRMImageMESA"); if (!glamor->egl_create_drm_image_mesa || !glamor->egl_export_drm_image_mesa) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, From 172e8cfcd411b1abeaf8ede2e3882d6198cee5b8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 15:05:02 -0400 Subject: [PATCH 179/462] glamor: Remove GLEW dependency. Glamor doesn't need to use GLEW. We can parse the extension by ourself. This patch also fix the fbo size checking from a hard coded style to a dynamic checking style. Signed-off-by: Zhigang Gong --- README | 42 ----------- configure.ac | 9 --- glamor/glamor.c | 43 +++++------ glamor/glamor_copyarea.c | 6 +- glamor/glamor_core.c | 131 ++++++++++++++++++++++------------ glamor/glamor_fill.c | 13 ++-- glamor/glamor_pixmap.c | 4 +- glamor/glamor_priv.h | 35 ++++----- glamor/glamor_render.c | 5 +- glamor/glamor_tile.c | 3 - hw/kdrive/ephyr/Makefile.am | 9 ++- hw/xfree86/glamor/Makefile.am | 2 +- 12 files changed, 141 insertions(+), 161 deletions(-) diff --git a/README b/README index fd31d9936..c240ac775 100644 --- a/README +++ b/README @@ -2,48 +2,6 @@ 1. Prerequirement. Please install makedepend and libudev-devel firstly. -Glamor need patch glew-1.5.8, here is the patch: - - -diff -ur ../Downloads/glew-1.5.8/Makefile glew-1.5.8/Makefile ---- ../Downloads/glew-1.5.8/Makefile 2011-01-31 22:17:27.000000000 +0800 -+++ glew-1.5.8/Makefile 2011-06-28 10:13:54.147700479 +0800 -@@ -63,8 +63,12 @@ - else - OPT = $(POPT) - endif --INCLUDE = -Iinclude -+ -+INCLUDE = -Iinclude - CFLAGS = $(OPT) $(WARN) $(INCLUDE) $(CFLAGS.EXTRA) -+ifeq ($(NO_GLX), 1) -+CFLAGS += -D_NO_GLX_ -+endif - - LIB.SRCS = src/glew.c - LIB.OBJS = $(LIB.SRCS:.c=.o) -diff -ur ../Downloads/glew-1.5.8/src/glew.c glew-1.5.8/src/glew.c ---- ../Downloads/glew-1.5.8/src/glew.c 2011-01-31 22:17:27.000000000 +0800 -+++ glew-1.5.8/src/glew.c 2011-06-28 10:06:45.952700777 +0800 -@@ -11379,6 +11379,10 @@ - { - GLenum r; - if ( (r = glewContextInit()) ) return r; -+#if defined(_NO_GLX_) -+ return r; -+#endif -+ - #if defined(_WIN32) - return wglewContextInit(); - #elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ - - -As xserver's glx extension code has conflicts with glew's glx related -initialization, we have to disable it in glew currently. Please apply the -above patch to glew and then build the glew as follow which will -workaround the problem. - -glew-1.5.8# NO_GLX=1 make 2. Build xserver-glamor. diff --git a/configure.ac b/configure.ac index a94cd009a..737aa8487 100644 --- a/configure.ac +++ b/configure.ac @@ -2036,15 +2036,6 @@ if test "$KDRIVE" = yes; then AC_MSG_ERROR([Xephyr dependencies missing]) fi - AC_CHECK_LIB(GLEW, glewInit, [ - AC_CHECK_HEADER(GL/glew.h, [], [ - AC_MSG_ERROR([requires glew http://glew.sourceforge.net/]) - ]) - ], [ - AC_MSG_ERROR([requires glew http://glew.sourceforge.net/]) - ]) - XEPHYR_LIBS="$XEPHYR_LIBS -lGLEW" - # Xephyr needs nanosleep() which is in librt on Solaris AC_CHECK_FUNC([nanosleep], [], AC_CHECK_LIB([rt], [nanosleep], XEPHYR_LIBS="$XEPHYR_LIBS -lrt")) diff --git a/glamor/glamor.c b/glamor/glamor.c index dd0d69db7..06103ace1 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -110,10 +110,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, GLuint tex; int type = GLAMOR_PIXMAP_TEXTURE; glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); if (w > 32767 || h > 32767) return NullPixmap; - if (!glamor_check_fbo_width_height(w,h) + if (!glamor_check_fbo_size(glamor_priv, w,h) || !glamor_check_fbo_depth(depth) || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. @@ -249,6 +250,7 @@ Bool glamor_init(ScreenPtr screen, unsigned int flags) { glamor_screen_private *glamor_priv; + int gl_version; #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); @@ -271,7 +273,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) LogMessage(X_WARNING, "glamor%d: Failed to allocate screen private\n", screen->myNum); - return FALSE; + goto fail; } dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); @@ -281,36 +283,27 @@ glamor_init(ScreenPtr screen, unsigned int flags) LogMessage(X_WARNING, "glamor%d: Failed to allocate pixmap private\n", screen->myNum); - return FALSE; + goto fail;; + } + + gl_version = glamor_gl_get_version(); + + if (gl_version < GLAMOR_GL_VERSION_ENCODE(1,3)) { + ErrorF("Require Opengl 1.3 or latter.\n"); + goto fail; } -#ifndef GLAMOR_GLES2 - glewInit(); - if (!GLEW_EXT_framebuffer_object) { - ErrorF("GL_EXT_framebuffer_object required\n"); - goto fail; - } - if (!GLEW_ARB_shader_objects) { - ErrorF("GL_ARB_shader_objects required\n"); - goto fail; - } - if (!GLEW_ARB_vertex_shader) { - ErrorF("GL_ARB_vertex_shader required\n"); - goto fail; - } - - if (!GLEW_ARB_pixel_buffer_object) { - ErrorF("GL_ARB_pixel_buffer_object required\n"); - goto fail; - } - - if (!GLEW_EXT_bgra) { - ErrorF("GL_EXT_bgra required\n"); +#ifdef GLAMOR_GLES2 + if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) { + ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); goto fail; } #endif + glamor_priv->has_pack_invert = glamor_gl_has_extension("GL_MESA_pack_invert"); + glamor_priv->has_fbo_blit = glamor_gl_has_extension("GL_EXT_framebuffer_blit"); + glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 7a84adbf2..dca7160f9 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -48,7 +48,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); int dst_x_off, dst_y_off, src_x_off, src_y_off, i; - if (!GLEW_EXT_framebuffer_blit) { + if (!glamor_priv->has_fbo_blit) { glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n"); return FALSE; } @@ -85,7 +85,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, for (i = 0; i < nbox; i++) { if(glamor_priv->yInverted) { - glBlitFramebufferEXT((box[i].x1 + dx + src_x_off), + glBlitFramebuffer((box[i].x1 + dx + src_x_off), (box[i].y1 + src_y_off), (box[i].x2 + dx + src_x_off), (box[i].y2 + src_y_off), @@ -101,7 +101,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, int flip_src_y1 = src_pixmap->drawable.height - (box[i].y2 + src_y_off); int flip_src_y2 = src_pixmap->drawable.height - (box[i].y1 + src_y_off); - glBlitFramebufferEXT(box[i].x1 + dx + src_x_off, + glBlitFramebuffer(box[i].x1 + dx + src_x_off, flip_src_y1, box[i].x2 + dx + src_x_off, flip_src_y2, diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 096e40b20..09851a0dd 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -201,35 +201,27 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glamor_priv->finish_access_prog[2] = glCreateProgram(); glamor_priv->finish_access_prog[3] = glCreateProgram(); - if (GLEW_ARB_fragment_shader) { #ifndef GLAMOR_GLES2 - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source); - glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); - glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source); + glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); + glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); - avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); - aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, aswizzle_source); - glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); - glAttachShader(glamor_priv->finish_access_prog[1], aswizzle_prog); + avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); + aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, aswizzle_source); + glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); + glAttachShader(glamor_priv->finish_access_prog[1], aswizzle_prog); #endif - es_vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); - es_fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_fs_source); - glAttachShader(glamor_priv->finish_access_prog[2], es_vs_prog); - glAttachShader(glamor_priv->finish_access_prog[2], es_fs_prog); + es_vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); + es_fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_fs_source); + glAttachShader(glamor_priv->finish_access_prog[2], es_vs_prog); + glAttachShader(glamor_priv->finish_access_prog[2], es_fs_prog); - es_avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); - es_aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_aswizzle_source); - glAttachShader(glamor_priv->finish_access_prog[3], es_avs_prog); - glAttachShader(glamor_priv->finish_access_prog[3], es_aswizzle_prog); + es_avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); + es_aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_aswizzle_source); + glAttachShader(glamor_priv->finish_access_prog[3], es_avs_prog); + glAttachShader(glamor_priv->finish_access_prog[3], es_aswizzle_prog); - } else { -#ifndef GLAMOR_GLES2 - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); - glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); - ErrorF("Lack of framgment shader support.\n"); -#endif - } #ifndef GLAMOR_GLES2 @@ -244,34 +236,32 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glBindAttribLocation(glamor_priv->finish_access_prog[3], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glamor_link_glsl_prog(glamor_priv->finish_access_prog[3]); - if (GLEW_ARB_fragment_shader) { - GLint sampler_uniform_location; + GLint sampler_uniform_location; #ifndef GLAMOR_GLES2 - sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[0]); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); + sampler_uniform_location = + glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[0]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); - sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[1]); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); + sampler_uniform_location = + glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[1]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); #endif - sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[2], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[2]); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); + sampler_uniform_location = + glGetUniformLocation(glamor_priv->finish_access_prog[2], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[2]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); - sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[3], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[3]); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); + sampler_uniform_location = + glGetUniformLocation(glamor_priv->finish_access_prog[3], "sampler"); + glUseProgram(glamor_priv->finish_access_prog[3]); + glUniform1i(sampler_uniform_location, 0); + glUseProgram(0); - } } void @@ -494,3 +484,50 @@ glamor_bitmap_to_region(PixmapPtr pixmap) glamor_finish_access(&pixmap->drawable); return ret; } + +/* Borrow from cairo. */ +Bool +glamor_gl_has_extension(char *extension) +{ + const char *gl_extensions; + char *pext; + int ext_len; + ext_len = strlen(extension); + + gl_extensions = (const char*)glGetString(GL_EXTENSIONS); + pext = (char*)gl_extensions; + + if (pext == NULL || extension == NULL) + return FALSE; + + while((pext = strstr(pext, extension)) != NULL) { + if (pext[ext_len] == ' ' || pext[ext_len] == '\0') + return TRUE; + pext += ext_len; + } + return FALSE; +} + +int +glamor_gl_get_version (void) +{ + int major, minor; + const char *version = (const char *) glGetString (GL_VERSION); + const char *dot = version == NULL ? NULL : strchr (version, '.'); + const char *major_start = dot; + + /* Sanity check */ + if (dot == NULL || dot == version || *(dot + 1) == '\0') { + major = 0; + minor = 0; + } else { + /* Find the start of the major version in the string */ + while (major_start > version && *major_start != ' ') + --major_start; + major = strtol (major_start, NULL, 10); + minor = strtol (dot + 1, NULL, 10); + } + + return GLAMOR_GL_VERSION_ENCODE (major, minor); +} + diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index bfa30b2e3..556ff342c 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -139,15 +139,10 @@ glamor_init_solid_shader(ScreenPtr screen) GLint fs_prog, vs_prog; glamor_priv->solid_prog = glCreateProgram(); - if (GLEW_ARB_fragment_shader) { - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs); - glAttachShader(glamor_priv->solid_prog, vs_prog); - glAttachShader(glamor_priv->solid_prog, fs_prog); - } else { - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs_only); - glAttachShader(glamor_priv->solid_prog, vs_prog); - } + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs); + fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs); + glAttachShader(glamor_priv->solid_prog, vs_prog); + glAttachShader(glamor_priv->solid_prog, fs_prog); glBindAttribLocation(glamor_priv->solid_prog, GLAMOR_VERTEX_POS, "v_position"); glamor_link_glsl_prog(glamor_priv->solid_prog); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index d747ade43..b105916d6 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -407,7 +407,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - if (!glamor_check_fbo_width_height(pixmap->drawable.width , pixmap->drawable.height) + if (!glamor_check_fbo_size(glamor_priv, 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); @@ -571,7 +571,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) // glPixelStorei(GL_PACK_ROW_LENGTH, 0); } - if (GLEW_MESA_pack_invert || glamor_priv->yInverted) { + if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index bf032b1cb..69590a5c5 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -37,8 +37,6 @@ #ifdef GLAMOR_GLES2 -#define GLEW_ES_ONLY 1 - #define GL_BGRA GL_BGRA_EXT #define GL_COLOR_INDEX 0x1900 #define GL_BITMAP 0x1A00 @@ -49,7 +47,6 @@ #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GLEW_ARB_fragment_shader 1 #define GL_PIXEL_PACK_BUFFER 0x88EB #define GL_PIXEL_UNPACK_BUFFER 0x88EC #define GL_CLAMP_TO_BORDER 0x812D @@ -66,7 +63,6 @@ #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#define GLEW_MESA_pack_invert 0 #define GL_PACK_INVERT_MESA 0x8758 #define glMapBuffer(x, y) NULL @@ -76,12 +72,13 @@ #endif -#ifdef GLAMOR_GLES2 #define GL_GLEXT_PROTOTYPES +#ifdef GLAMOR_GLES2 #include #include #else -#include +#include +#include #endif @@ -90,19 +87,11 @@ #endif -#ifndef MAX_WIDTH -#define MAX_WIDTH 4096 -#endif - -#ifndef MAX_HEIGHT -#define MAX_HEIGHT 4096 -#endif - #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_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \ + && (_w_) < _glamor_->max_fbo_size \ + && (_h_) < _glamor_->max_fbo_size) #define glamor_check_fbo_depth(_depth_) ( \ _depth_ == 8 \ @@ -241,6 +230,9 @@ typedef struct glamor_screen_private { char *vb; int vb_stride; enum glamor_gl_flavor gl_flavor; + int has_pack_invert; + int has_fbo_blit; + int max_fbo_size; /* glamor_finishaccess */ GLint finish_access_prog[4]; @@ -674,6 +666,15 @@ void glamor_set_transform_for_pixmap(PixmapPtr pixmap, glamor_transform_uniforms *uniform_locations); Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); +Bool glamor_gl_has_extension(char *extension); +int glamor_gl_get_version(void); + +#define GLAMOR_GL_VERSION_ENCODE(major, minor) ( \ + ((major) * 256) \ + + ((minor) * 1)) + + + /* glamor_fill.c */ void glamor_fill(DrawablePtr drawable, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 0567f6717..12b09243d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1154,6 +1154,7 @@ glamor_composite(CARD8 op, PicturePtr temp_src = source, temp_mask = mask; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; glamor_composite_rect_t rect; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); x_temp_src = x_source; y_temp_src = y_source; @@ -1181,7 +1182,7 @@ glamor_composite(CARD8 op, && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) && ((width * height * 4 < (source_pixmap->drawable.width * source_pixmap->drawable.height)) - || !(glamor_check_fbo_width_height(source_pixmap->drawable.width, + || !(glamor_check_fbo_size(glamor_priv, source_pixmap->drawable.width, source_pixmap->drawable.height))))) { temp_src = glamor_convert_gradient_picture(screen, source, x_source, y_source, width, height); if (!temp_src) { @@ -1197,7 +1198,7 @@ glamor_composite(CARD8 op, && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) && ((width * height * 4 < (mask_pixmap->drawable.width * mask_pixmap->drawable.height)) - || !(glamor_check_fbo_width_height(mask_pixmap->drawable.width, + || !(glamor_check_fbo_size(glamor_priv, mask_pixmap->drawable.width, mask_pixmap->drawable.height)))))) { /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity * to do reduce one convertion. */ diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index cdb0611c6..cb235527d 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -74,9 +74,6 @@ glamor_init_tile_shader(ScreenPtr screen) GLint fs_prog, vs_prog; GLint sampler_uniform_location; - if (!GLEW_ARB_fragment_shader) - return; - glamor_priv->tile_prog = glCreateProgram(); vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, tile_vs); fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs); diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 7e10d6b79..744604eea 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -66,6 +66,12 @@ libxephyr_la_SOURCES = $(XEPHYR_SRCS) Xephyr_SOURCES = \ ephyrinit.c +if GLAMOR_GLES2 +GLAMOR_GL_LIB = -lGLESv2 +else +GLAMOR_GL_LIB = -lGL +endif + Xephyr_LDADD = \ libxephyr.la \ libxephyr-hostx.la \ @@ -74,7 +80,8 @@ Xephyr_LDADD = \ $(top_builddir)/exa/libexa.la \ $(top_builddir)/glamor/libglamor.la \ @KDRIVE_LIBS@ \ - @XEPHYR_LIBS@ + @XEPHYR_LIBS@ \ + $(GLAMOR_GL_LIB) Xephyr_DEPENDENCIES = \ libxephyr.la \ diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index a00f08ac5..dcd44b2d8 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -15,7 +15,7 @@ if GLAMOR_GLES2 glamor_la_CFLAGS+=-DGLAMOR_GLES2 GLAMOR_GL_LIB = -lGLESv2 else -GLAMOR_GL_LIB = -L$(libdir)/../lib64 -lGLEW +GLAMOR_GL_LIB = -lGL endif glamor_la_LDFLAGS = \ From 5e7fdbb498c47b6e89280b8354f0ebaaf61d0646 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 15:08:12 -0400 Subject: [PATCH 180/462] glamor: Disable ALPHA8 fbo. As some platform doesn't support to use ALPHA8 texture as draw target, we have to disable it. It seems there is no easy way to check that. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 ++ glamor/glamor_pixmap.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 06103ace1..cd261ac8b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -146,9 +146,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return pixmap; switch (depth) { +#if 0 case 8: format = GL_ALPHA; break; +#endif case 24: format = GL_RGB; break; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index b105916d6..5ac62f4e7 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -219,9 +219,11 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, GLenum iformat; switch (pixmap->drawable.depth) { +#if 0 case 8: iformat = GL_ALPHA; break; +#endif case 24: iformat = GL_RGB; break; From 667d65534d64df30146cfa0d32522bced51e0697 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 15:27:12 -0400 Subject: [PATCH 181/462] glamor: Unify the variable name which used to indicate no alpha. The original code use different name and the name is vague. Now change it to no_alpha. Signed-off-by: Zhigang Gong --- glamor/glamor_getspans.c | 4 ++-- glamor/glamor_pixmap.c | 39 ++++++++++++++++++++------------------- glamor/glamor_priv.h | 24 ++++++++++++------------ glamor/glamor_putimage.c | 8 ++++---- glamor/glamor_setspans.c | 5 +++-- 5 files changed, 41 insertions(+), 39 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 237c1e789..e1a20baef 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -41,7 +41,7 @@ glamor_get_spans(DrawablePtr drawable, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - int ax; + int no_alpha; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int i; @@ -56,7 +56,7 @@ glamor_get_spans(DrawablePtr drawable, if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &ax + &no_alpha )) { glamor_fallback("unknown depth. %d \n", drawable->depth); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 5ac62f4e7..8ca1318ab 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -272,7 +272,8 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, * */ static void -_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, int ax, int flip) +_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, + GLenum type, int no_alpha, int flip) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -299,7 +300,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ - if (ax == 0 && !need_flip) { + if (no_alpha == 0 && !need_flip) { __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->tex); return; } @@ -341,9 +342,9 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, i glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); #if 0 - glUseProgram(glamor_priv->finish_access_prog[ax]); + glUseProgram(glamor_priv->finish_access_prog[no_alpha]); #else - glUseProgram(glamor_priv->finish_access_prog[ax + 2]); + glUseProgram(glamor_priv->finish_access_prog[no_alpha + 2]); #endif glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -397,13 +398,13 @@ glamor_pixmap_ensure_fb(PixmapPtr pixmap) /* * Prepare to upload a pixmap to texture memory. - * ax 1 means the format needs to wire alpha to 1. + * no_alpha equals 1 means the format needs to wire alpha to 1. * Two condtion need to setup a fbo for a pixmap * 1. !yInverted, we need to do flip if we are not yInverted. - * 2. ax != 0, we need to wire the alpha. + * 2. no_alpha != 0, we need to wire the alpha. * */ static int -glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) +glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha) { int need_fbo; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -419,7 +420,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int ax) if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return 0; - if (ax != 0 || !glamor_priv->yInverted) + if (no_alpha != 0 || !glamor_priv->yInverted) need_fbo = 1; else need_fbo = 0; @@ -444,16 +445,16 @@ enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap) { GLenum format, type; - int ax; + int no_alpha; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &ax)) { + &no_alpha)) { glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); return GLAMOR_UPLOAD_FAILED; } - if (glamor_pixmap_upload_prepare(pixmap, ax)) + if (glamor_pixmap_upload_prepare(pixmap, no_alpha)) return GLAMOR_UPLOAD_FAILED; glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD, "Uploading pixmap %p %dx%d depth%d.\n", @@ -461,7 +462,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth); - _glamor_upload_pixmap_to_texture(pixmap, format, type, ax, 1); + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, 1); return GLAMOR_UPLOAD_DONE; } @@ -485,16 +486,16 @@ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap) { GLenum format, type; - int ax; + int no_alpha; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &ax)) { + &no_alpha)) { ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); assert(0); } - _glamor_upload_pixmap_to_texture(pixmap, format, type, ax, 1); + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, 1); } @@ -514,7 +515,7 @@ 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; + int no_alpha; uint8_t *data, *read; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); @@ -522,12 +523,10 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; - /* XXX we may don't need to validate it on GPU here, - * we can just validate it on CPU. */ if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &ax)) { + &no_alpha)) { ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); assert(0); // Should never happen. return FALSE; @@ -543,6 +542,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) stride = pixmap->devKind; glamor_set_destination_pixmap_priv_nc(pixmap_priv); + /* XXX we may don't need to validate it on GPU here, + * we can just validate it on CPU. */ glamor_validate_pixmap(pixmap); switch (access) { case GLAMOR_ACCESS_RO: diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 69590a5c5..2c2bf22d2 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -404,7 +404,7 @@ format_for_pixmap(PixmapPtr pixmap) /* * 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. + * no_alpha is used to indicate whehter we need to wire alpha to 1. * * Return 0 if find a matched texture type. Otherwise return -1. **/ @@ -412,41 +412,41 @@ static inline int glamor_get_tex_format_type_from_pictformat(PictFormatShort format, GLenum *tex_format, GLenum *tex_type, - int *xa) + int *no_alpha) { - *xa = 0; + *no_alpha = 0; switch (format) { case PICT_a1: *tex_format = GL_COLOR_INDEX; *tex_type = GL_BITMAP; break; case PICT_b8g8r8x8: - *xa = 1; + *no_alpha = 1; case PICT_b8g8r8a8: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_8_8_8_8; break; case PICT_x8r8g8b8: - *xa = 1; + *no_alpha = 1; case PICT_a8r8g8b8: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; break; case PICT_x8b8g8r8: - *xa = 1; + *no_alpha = 1; case PICT_a8b8g8r8: *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; break; case PICT_x2r10g10b10: - *xa = 1; + *no_alpha = 1; case PICT_a2r10g10b10: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; break; case PICT_x2b10g10r10: - *xa = 1; + *no_alpha = 1; case PICT_a2b10g10r10: *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; @@ -461,14 +461,14 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV; break; case PICT_x1b5g5r5: - *xa = 1; + *no_alpha = 1; case PICT_a1b5g5r5: *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; case PICT_x1r5g5b5: - *xa = 1; + *no_alpha = 1; case PICT_a1r5g5b5: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; @@ -478,14 +478,14 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, *tex_type = GL_UNSIGNED_BYTE; break; case PICT_x4r4g4b4: - *xa = 1; + *no_alpha = 1; case PICT_a4r4g4b4: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; break; case PICT_x4b4g4r4: - *xa = 1; + *no_alpha = 1; case PICT_a4b4g4r4: *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index a6aadce11..38da796af 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -265,7 +265,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, float vertices[8], texcoords[8]; GLfloat xscale, yscale, txscale, tyscale; GLuint tex; - int ax = 0; + int no_alpha; if (image_format == XYBitmap) { assert(depth == 1); goto fail; @@ -290,7 +290,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &ax + &no_alpha )) { glamor_fallback("unknown depth. %d \n", drawable->depth); @@ -347,9 +347,9 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glEnable(GL_TEXTURE_2D); #if 0 - glUseProgram(glamor_priv->finish_access_prog[ax]); + glUseProgram(glamor_priv->finish_access_prog[no_alpha]); #else - glUseProgram(glamor_priv->finish_access_prog[ax + 2]); + glUseProgram(glamor_priv->finish_access_prog[no_alpha + 2]); #endif x += drawable->x; diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index af2664301..d08be135f 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -37,18 +37,19 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - int ax, i; + int no_alpha, i; uint8_t *drawpixels_src = (uint8_t *)src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; + goto fail; if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, &format, &type, - &ax + &no_alpha )) { glamor_fallback("unknown depth. %d \n", drawable->depth); From 5cbb2a4ca05f696d2af9a2e50bf106b6f2acd1c6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 15:35:26 -0400 Subject: [PATCH 182/462] glamor: Only fallbac glamor_setspan when we are using gles2. Signed-off-by: Zhigang Gong --- glamor/glamor_setspans.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index d08be135f..a1d5dc1a6 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -36,6 +36,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + glamor_screen_private *glamor_priv; GLenum format, type; int no_alpha, i; uint8_t *drawpixels_src = (uint8_t *)src; @@ -43,8 +44,10 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, BoxRec *pbox; int x_off, y_off; + glamor_priv = glamor_get_screen_private(drawable->pScreen); - goto fail; + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + goto fail; if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, &format, From a228effbeb339ae6f0b73c633022b3ec9981148f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 11 Aug 2011 15:56:02 -0400 Subject: [PATCH 183/462] glamor: Remove useless glVertexPointer related code. As glVertexPointer is not supported by GLES2, I totally replaced it by VertexAttribArray. This commit remove those old code. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 22 +---------- glamor/glamor_core.c | 83 ++++++---------------------------------- glamor/glamor_fill.c | 31 --------------- glamor/glamor_pixmap.c | 20 +--------- glamor/glamor_priv.h | 2 +- glamor/glamor_putimage.c | 11 +----- glamor/glamor_render.c | 30 --------------- glamor/glamor_tile.c | 35 ----------------- 8 files changed, 15 insertions(+), 219 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index dca7160f9..1e160acb6 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -180,15 +180,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src, -#if 0 - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); @@ -201,19 +196,12 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); -#if 0 - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glUseProgram(glamor_priv->finish_access_prog[0]); -#else glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glUseProgram(glamor_priv->finish_access_prog[2]); -#endif + glUseProgram(glamor_priv->finish_access_prog[0]); } else { @@ -240,19 +228,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } -#if 0 - glDisableClientState(GL_VERTEX_ARRAY); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); - } -#else glDisableVertexAttribArray(GLAMOR_VERTEX_POS); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glDisable(GL_TEXTURE_2D); } -#endif glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ if (flush_needed) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 09851a0dd..9f0457380 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -141,30 +141,7 @@ void glamor_init_finish_access_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); -#ifndef GLAMOR_GLES2 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"; -#endif - const char *es_vs_source = "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" "varying vec2 source_texture;\n" @@ -174,7 +151,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) " source_texture = v_texcoord0.xy;\n" "}\n"; - const char *es_fs_source = + const char *fs_source = "varying vec2 source_texture;\n" "uniform sampler2D sampler;\n" "void main()\n" @@ -182,62 +159,37 @@ glamor_init_finish_access_shaders(ScreenPtr screen) " gl_FragColor = texture2D(sampler, source_texture);\n" "}\n"; - const char *es_aswizzle_source = + const char *set_alpha_source = "varying vec2 source_texture;\n" - "varying vec2 texcoords;\n" "uniform sampler2D sampler;\n" "void main()\n" "{\n" " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" "}\n"; - - - - GLint fs_prog, vs_prog, avs_prog, aswizzle_prog; - GLint es_fs_prog, es_vs_prog, es_avs_prog, es_aswizzle_prog; + GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; + GLint sampler_uniform_location; glamor_priv->finish_access_prog[0] = glCreateProgram(); glamor_priv->finish_access_prog[1] = glCreateProgram(); - glamor_priv->finish_access_prog[2] = glCreateProgram(); - glamor_priv->finish_access_prog[3] = glCreateProgram(); -#ifndef GLAMOR_GLES2 vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source); glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); - aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, aswizzle_source); + set_alpha_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, set_alpha_source); glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); - glAttachShader(glamor_priv->finish_access_prog[1], aswizzle_prog); -#endif - es_vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); - es_fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_fs_source); - glAttachShader(glamor_priv->finish_access_prog[2], es_vs_prog); - glAttachShader(glamor_priv->finish_access_prog[2], es_fs_prog); + glAttachShader(glamor_priv->finish_access_prog[1], set_alpha_prog); - es_avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, es_vs_source); - es_aswizzle_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, es_aswizzle_source); - glAttachShader(glamor_priv->finish_access_prog[3], es_avs_prog); - glAttachShader(glamor_priv->finish_access_prog[3], es_aswizzle_prog); - - - -#ifndef GLAMOR_GLES2 + glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_POS, "v_position"); + glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]); + + glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_POS, "v_position"); + glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]); -#endif - glBindAttribLocation(glamor_priv->finish_access_prog[2], GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(glamor_priv->finish_access_prog[2], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(glamor_priv->finish_access_prog[2]); - glBindAttribLocation(glamor_priv->finish_access_prog[3], GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(glamor_priv->finish_access_prog[3], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(glamor_priv->finish_access_prog[3]); - - GLint sampler_uniform_location; -#ifndef GLAMOR_GLES2 sampler_uniform_location = glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); glUseProgram(glamor_priv->finish_access_prog[0]); @@ -249,19 +201,6 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glUseProgram(glamor_priv->finish_access_prog[1]); glUniform1i(sampler_uniform_location, 0); glUseProgram(0); -#endif - sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[2], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[2]); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); - - sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[3], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[3]); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); - } void diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 556ff342c..660ffe014 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -102,33 +102,11 @@ void glamor_init_solid_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - const char *solid_vs_only = -#if 0 -#else - "attribute vec4 v_position;" -#endif - "uniform vec4 color;\n" - "void main()\n" - "{\n" -#if 0 - " gl_Position = gl_Vertex;\n" -#else - " gl_Position = v_position;\n" -#endif - " gl_Color = color;\n" - "}\n"; const char *solid_vs = -#if 0 -#else "attribute vec4 v_position;" -#endif "void main()\n" "{\n" -#if 0 - " gl_Position = gl_Vertex;\n" -#else " gl_Position = v_position;\n" -#endif "}\n"; const char *solid_fs = "uniform vec4 color;\n" @@ -201,25 +179,16 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); -#if 0 - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -#if 0 - glDisableClientState(GL_VERTEX_ARRAY); -#else glDisableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif glUseProgram(0); return TRUE; fail: diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 8ca1318ab..1dc1ee93c 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -32,14 +32,9 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, glamor_pixmap_private *pixmap_priv) { GLfloat vertices[8]; -#if 0 - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif glUseProgram(glamor_priv->solid_prog); glUniform4fv(glamor_priv->solid_color_uniform_location, 1, pixmap_priv->pending_op.fill.color4fv); @@ -52,11 +47,7 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, vertices[6] = -1; vertices[7] = 1; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -#if 0 - glDisableClientState(GL_VERTEX_ARRAY); -#else glDisableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif glUseProgram(0); pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } @@ -341,23 +332,14 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); -#if 0 glUseProgram(glamor_priv->finish_access_prog[no_alpha]); -#else - glUseProgram(glamor_priv->finish_access_prog[no_alpha + 2]); -#endif glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisable(GL_TEXTURE_2D); glUseProgram(0); -#if 0 - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -#else glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); -#endif glDeleteTextures(1, &tex); glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -516,7 +498,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) unsigned int stride, row_length, y; GLenum format, type, gl_access, gl_usage; int no_alpha; - uint8_t *data, *read; + uint8_t *data = NULL, *read; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 2c2bf22d2..400988574 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -235,7 +235,7 @@ typedef struct glamor_screen_private { int max_fbo_size; /* glamor_finishaccess */ - GLint finish_access_prog[4]; + GLint finish_access_prog[2]; /* glamor_solid */ GLint solid_prog; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 38da796af..addfdf2bd 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -35,8 +35,8 @@ void glamor_init_putimage_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); #if 0 + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); const char *xybitmap_vs = "uniform float x_bias;\n" "uniform float x_scale;\n" @@ -346,11 +346,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); -#if 0 glUseProgram(glamor_priv->finish_access_prog[no_alpha]); -#else - glUseProgram(glamor_priv->finish_access_prog[no_alpha + 2]); -#endif x += drawable->x; y += drawable->y; @@ -400,13 +396,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glDisable(GL_TEXTURE_2D); glUseProgram(0); -#if 0 - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -#else glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); -#endif glDeleteTextures(1, &tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 12b09243d..6099af744 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -523,47 +523,25 @@ glamor_setup_composite_vbo(ScreenPtr screen) glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); -#if 0 - glVertexPointer(2, GL_FLOAT, glamor_priv->vb_stride, - (void *)((long)glamor_priv->vbo_offset)); - glEnableClientState(GL_VERTEX_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset)); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif if (glamor_priv->has_source_coords) { -#if 0 - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, glamor_priv->vb_stride, - (void *)(glamor_priv->vbo_offset + 2 * sizeof(float))); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset + 2 * sizeof(float))); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); -#endif } if (glamor_priv->has_mask_coords) { -#if 0 - 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); -#else glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset + (glamor_priv->has_source_coords ? 4 : 2) * sizeof(float))); glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); -#endif } } @@ -1054,17 +1032,9 @@ glamor_composite_with_shader(CARD8 op, glamor_flush_composite_rects(screen); glBindBuffer(GL_ARRAY_BUFFER, 0); -#if 0 - glClientActiveTexture(GL_TEXTURE0); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTexture(GL_TEXTURE1); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); -#else glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); -#endif REGION_UNINIT(dst->pDrawable->pScreen, ®ion); glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index cb235527d..5104f0b47 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -41,35 +41,20 @@ glamor_init_tile_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); const char *tile_vs = -#if 0 -#else "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" "varying vec2 tile_texture;\n" -#endif "void main()\n" "{\n" -#if 0 - " gl_Position = gl_Vertex;\n" - " gl_TexCoord[0] = gl_MultiTexCoord0;\n" -#else " gl_Position = v_position;\n" " tile_texture = v_texcoord0.xy;\n" -#endif "}\n"; const char *tile_fs = -#if 0 -#else "varying vec2 tile_texture;\n" -#endif "uniform sampler2D sampler;\n" "void main()\n" "{\n" -#if 0 - " gl_FragColor = texture2D(sampler, gl_TexCoord[0].xy);\n" -#else " gl_FragColor = texture2D(sampler, tile_texture);\n" -#endif "}\n"; GLint fs_prog, vs_prog; GLint sampler_uniform_location; @@ -163,16 +148,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords); -#if 0 - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, source_texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), source_texcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); -#endif } else { GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); @@ -183,31 +162,17 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_priv->yInverted, vertices); -#if 0 - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -#if 0 - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - glClientActiveTexture(GL_TEXTURE0); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); - } - glDisableClientState(GL_VERTEX_ARRAY); -#else if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glDisable(GL_TEXTURE_2D); } glDisableVertexAttribArray(GLAMOR_VERTEX_POS); -#endif glUseProgram(0); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); From 23c1fba5e5a5fe8dd18c4c8a9b5a958ce4671160 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 13 Aug 2011 15:41:18 -0400 Subject: [PATCH 184/462] glamor: Remove glu3 which is unnecessary. Signed-off-by: Zhigang Gong --- configure.ac | 1 - glamor/Makefile.am | 5 +- glamor/glu3/Makefile.am | 15 -- glamor/glu3/glu3.h | 161 ---------------- glamor/glu3/glu3_scalar.h | 388 -------------------------------------- glamor/glu3/matrix.c | 217 --------------------- 6 files changed, 1 insertion(+), 786 deletions(-) delete mode 100644 glamor/glu3/Makefile.am delete mode 100644 glamor/glu3/glu3.h delete mode 100644 glamor/glu3/glu3_scalar.h delete mode 100644 glamor/glu3/matrix.c diff --git a/configure.ac b/configure.ac index 737aa8487..69b1ac3c5 100644 --- a/configure.ac +++ b/configure.ac @@ -2163,7 +2163,6 @@ Xi/Makefile xfixes/Makefile exa/Makefile glamor/Makefile -glamor/glu3/Makefile hw/Makefile hw/xfree86/Makefile hw/xfree86/common/Makefile diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 2df76bd53..ec38ac4e8 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -4,8 +4,6 @@ noinst_LTLIBRARIES = libglamor.la # built (in hw/xfree86/os-support/solaris) until after glamor is built SOLARIS_ASM_CFLAGS="" -SUBDIRS = glu3 - if XORG sdk_HEADERS = glamor.h endif @@ -39,5 +37,4 @@ libglamor_la_SOURCES = \ glamor_picture.c\ glamor_window.c\ glamor.h -libglamor_la_LIBADD = \ - glu3/libglu3.la + diff --git a/glamor/glu3/Makefile.am b/glamor/glu3/Makefile.am deleted file mode 100644 index 7d141a7fc..000000000 --- a/glamor/glu3/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -noinst_LTLIBRARIES = libglu3.la - -# Override these since glu3 doesn't need them and the needed files aren't -# built (in hw/xfree86/os-support/solaris) until after glu3 is built -SOLARIS_ASM_CFLAGS="" - -INCLUDES = \ - $(XORG_INCS) - -AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) - -libglu3_la_SOURCES = \ - matrix.c \ - glu3.h \ - glu3_scalar.h diff --git a/glamor/glu3/glu3.h b/glamor/glu3/glu3.h deleted file mode 100644 index 0a698cc02..000000000 --- a/glamor/glu3/glu3.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright © 2009 Ian D. Romanick - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __glu3_h__ -#define __glu3_h__ - -#include - -#define GLU_VERSION_3_0 - -struct GLUmat4; - -struct GLUvec4 { - GLfloat values[4]; - -#ifdef __cplusplus - inline GLUvec4(void) - { - } - - inline GLUvec4(GLfloat x , GLfloat y, GLfloat z, GLfloat w) - { - values[0] = x; - values[1] = y; - values[2] = z; - values[3] = w; - } - - inline GLUvec4(const GLUvec4 &v) - { - values[0] = v.values[0]; - values[1] = v.values[1]; - values[2] = v.values[2]; - values[3] = v.values[3]; - } - - GLUvec4 operator *(const GLUmat4 &) const; - GLUvec4 operator *(const GLUvec4 &) const; - GLUvec4 operator *(GLfloat) const; - - GLUvec4 operator +(const GLUvec4 &) const; - GLUvec4 operator -(const GLUvec4 &) const; -#endif /* __cplusplus */ -}; - - -struct GLUmat4 { - struct GLUvec4 col[4]; - -#ifdef __cplusplus - inline GLUmat4(void) - { - } - - inline GLUmat4(const GLUvec4 & c0, const GLUvec4 & c1, - const GLUvec4 & c2, const GLUvec4 & c3) - { - col[0] = c0; - col[1] = c1; - col[2] = c2; - col[3] = c3; - } - - inline GLUmat4(const GLUmat4 &m) - { - col[0] = m.col[0]; - col[1] = m.col[1]; - col[2] = m.col[2]; - col[3] = m.col[3]; - } - - - GLUvec4 operator *(const GLUvec4 &) const; - GLUmat4 operator *(const GLUmat4 &) const; - GLUmat4 operator *(GLfloat) const; - - GLUmat4 operator +(const GLUmat4 &) const; - GLUmat4 operator -(const GLUmat4 &) const; -#endif /* __cplusplus */ -}; - -#define GLU_MAX_STACK_DEPTH 32 - -struct GLUmat4Stack { - struct GLUmat4 stack[GLU_MAX_STACK_DEPTH]; - unsigned top; - -#ifdef __cplusplus - GLUmat4Stack() : top(0) - { - /* empty */ - } -#endif /* __cplusplus */ -}; - -#ifndef __cplusplus -typedef struct GLUvec4 GLUvec4; -typedef struct GLUmat4 GLUmat4; -typedef struct GLUmat4Stack GLUmat4Stack; -#endif /* __cplusplus */ - - -#ifdef __cplusplus -extern "C" { -#endif - -void gluScale4v(GLUmat4 *result, const GLUvec4 *); -void gluTranslate4v(GLUmat4 *result, const GLUvec4 *); -void gluRotate4v(GLUmat4 *result, const GLUvec4 *axis, GLfloat angle); -void gluLookAt4v(GLUmat4 *result, const GLUvec4 *eye, const GLUvec4 *center, - const GLUvec4 *up); -void gluPerspective4f(GLUmat4 *result, GLfloat fovy, GLfloat aspect, - GLfloat near, GLfloat far); -void gluFrustum6f(GLUmat4 *result, - GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat near, GLfloat far); -void gluOrtho6f(GLUmat4 *result, - GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat near, GLfloat far); -extern const GLUmat4 gluIdentityMatrix; - -#ifdef __cplusplus -}; -#endif - -#ifdef __cplusplus -GLfloat gluDot4(const GLUvec4 &, const GLUvec4 &); -GLfloat gluDot3(const GLUvec4 &, const GLUvec4 &); -GLfloat gluDot2(const GLUvec4 &, const GLUvec4 &); - -GLUvec4 gluCross(const GLUvec4 &, const GLUvec4 &); -GLUvec4 gluNormalize(const GLUvec4 &); -GLfloat gluLength(const GLUvec4 &); -GLfloat gluLengthSqr(const GLUvec4 &); -#endif /* __cplusplus */ - -#include "glu3_scalar.h" - -#endif /* __glu3_h__ */ diff --git a/glamor/glu3/glu3_scalar.h b/glamor/glu3/glu3_scalar.h deleted file mode 100644 index 00592f0dc..000000000 --- a/glamor/glu3/glu3_scalar.h +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright © 2009 Ian D. Romanick - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -static inline void gluMult4v_4v(GLUvec4 *result, - const GLUvec4 *v1, const GLUvec4 *v2) -{ - result->values[0] = v1->values[0] * v2->values[0]; - result->values[1] = v1->values[1] * v2->values[1]; - result->values[2] = v1->values[2] * v2->values[2]; - result->values[3] = v1->values[3] * v2->values[3]; -} - - -static inline void gluDiv4v_4v(GLUvec4 *result, - const GLUvec4 *v1, const GLUvec4 *v2) -{ - result->values[0] = v1->values[0] / v2->values[0]; - result->values[1] = v1->values[1] / v2->values[1]; - result->values[2] = v1->values[2] / v2->values[2]; - result->values[3] = v1->values[3] / v2->values[3]; -} - - -static inline void gluAdd4v_4v(GLUvec4 *result, - const GLUvec4 *v1, const GLUvec4 *v2) -{ - result->values[0] = v1->values[0] + v2->values[0]; - result->values[1] = v1->values[1] + v2->values[1]; - result->values[2] = v1->values[2] + v2->values[2]; - result->values[3] = v1->values[3] + v2->values[3]; -} - - -static inline void gluSub4v_4v(GLUvec4 *result, - const GLUvec4 *v1, const GLUvec4 *v2) -{ - result->values[0] = v1->values[0] - v2->values[0]; - result->values[1] = v1->values[1] - v2->values[1]; - result->values[2] = v1->values[2] - v2->values[2]; - result->values[3] = v1->values[3] - v2->values[3]; -} - - -static inline void gluMult4v_f(GLUvec4 *result, - const GLUvec4 *v1, GLfloat f) -{ - result->values[0] = v1->values[0] * f; - result->values[1] = v1->values[1] * f; - result->values[2] = v1->values[2] * f; - result->values[3] = v1->values[3] * f; -} - - -static inline void gluDiv4v_f(GLUvec4 *result, - const GLUvec4 *v1, GLfloat f) -{ - result->values[0] = v1->values[0] / f; - result->values[1] = v1->values[1] / f; - result->values[2] = v1->values[2] / f; - result->values[3] = v1->values[3] / f; -} - - -static inline void gluAdd4v_f(GLUvec4 *result, - const GLUvec4 *v1, GLfloat f) -{ - result->values[0] = v1->values[0] + f; - result->values[1] = v1->values[1] + f; - result->values[2] = v1->values[2] + f; - result->values[3] = v1->values[3] + f; -} - - -static inline void gluSub4v_f(GLUvec4 *result, - const GLUvec4 *v1, GLfloat f) -{ - result->values[0] = v1->values[0] - f; - result->values[1] = v1->values[1] - f; - result->values[2] = v1->values[2] - f; - result->values[3] = v1->values[3] - f; -} - - -static inline void gluMult4m_f(GLUmat4 *result, - const GLUmat4 *m, GLfloat f) -{ - GLUmat4 temp; - - gluMult4v_f(& temp.col[0], & m->col[0], f); - gluMult4v_f(& temp.col[1], & m->col[1], f); - gluMult4v_f(& temp.col[2], & m->col[2], f); - gluMult4v_f(& temp.col[3], & m->col[3], f); - *result = temp; -} - - -static inline void gluMult4m_4v(GLUvec4 *result, - const GLUmat4 *m, const GLUvec4 *v) -{ - GLUvec4 temp[6]; - unsigned i; - - for (i = 0; i < 4; i++) { - gluMult4v_f(& temp[i], & m->col[i], v->values[i]); - } - - gluAdd4v_4v(& temp[4], & temp[0], & temp[1]); - gluAdd4v_4v(& temp[5], & temp[2], & temp[3]); - gluAdd4v_4v(result, & temp[4], & temp[5]); -} - - -static inline void gluAdd4m_4m(GLUmat4 *result, - const GLUmat4 *m1, const GLUmat4 *m2) -{ - GLUmat4 temp; - - gluAdd4v_4v(& temp.col[0], & m1->col[0], & m2->col[0]); - gluAdd4v_4v(& temp.col[1], & m1->col[1], & m2->col[1]); - gluAdd4v_4v(& temp.col[2], & m1->col[2], & m2->col[2]); - gluAdd4v_4v(& temp.col[3], & m1->col[3], & m2->col[3]); - *result = temp; -} - -static inline void gluSub4m_4m(GLUmat4 *result, - const GLUmat4 *m1, const GLUmat4 *m2) -{ - GLUmat4 temp; - - gluSub4v_4v(& temp.col[0], & m1->col[0], & m2->col[0]); - gluSub4v_4v(& temp.col[1], & m1->col[1], & m2->col[1]); - gluSub4v_4v(& temp.col[2], & m1->col[2], & m2->col[2]); - gluSub4v_4v(& temp.col[3], & m1->col[3], & m2->col[3]); - *result = temp; -} - -static inline GLfloat gluDot4_4v(const GLUvec4 *v1, const GLUvec4 *v2) -{ - return v1->values[0] * v2->values[0] - + v1->values[1] * v2->values[1] - + v1->values[2] * v2->values[2] - + v1->values[3] * v2->values[3]; -} - - -static inline GLfloat gluDot3_4v(const GLUvec4 *v1, const GLUvec4 *v2) -{ - return v1->values[0] * v2->values[0] - + v1->values[1] * v2->values[1] - + v1->values[2] * v2->values[2]; -} - - -static inline GLfloat gluDot2_4v(const GLUvec4 *v1, const GLUvec4 *v2) -{ - return v1->values[0] * v2->values[0] - + v1->values[1] * v2->values[1]; -} - - -static inline void gluCross4v(GLUvec4 *result, - const GLUvec4 *v1, const GLUvec4 *v2) -{ - GLUvec4 temp; - - temp.values[0] = (v1->values[1] * v2->values[2]) - - (v1->values[2] * v2->values[1]); - temp.values[1] = (v1->values[2] * v2->values[0]) - - (v1->values[0] * v2->values[2]); - temp.values[2] = (v1->values[0] * v2->values[1]) - - (v1->values[1] * v2->values[0]); - temp.values[3] = 0.0; - *result = temp; -} - - -static inline void gluOuter4v(GLUmat4 *result, - const GLUvec4 *v1, const GLUvec4 *v2) -{ - GLUmat4 temp; - - gluMult4v_f(& temp.col[0], v1, v2->values[0]); - gluMult4v_f(& temp.col[1], v1, v2->values[1]); - gluMult4v_f(& temp.col[2], v1, v2->values[2]); - gluMult4v_f(& temp.col[3], v1, v2->values[3]); - *result = temp; -} - - -static inline GLfloat gluLengthSqr4v(const GLUvec4 *v) -{ - return gluDot4_4v(v, v); -} - - -static inline GLfloat gluLength4v(const GLUvec4 *v) -{ - return sqrt(gluLengthSqr4v(v)); -} - - -static inline void gluNormalize4v(GLUvec4 *result, const GLUvec4 *v) -{ - gluDiv4v_f(result, v, gluLength4v(v)); -} - - - -static inline void gluTranspose4m(GLUmat4 *result, const GLUmat4 *m) -{ - unsigned i; - unsigned j; - GLUmat4 temp; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - temp.col[i].values[j] = m->col[j].values[i]; - } - } - - *result = temp; -} - - -static inline void gluMult4m_4m(GLUmat4 *result, - const GLUmat4 *m1, const GLUmat4 *m2) -{ - GLUmat4 temp; - unsigned i; - - for (i = 0; i < 4; i++) { - gluMult4m_4v(& temp.col[i], m1, & m2->col[i]); - } - - *result = temp; -} - - - -static inline void gluTranslate3f(GLUmat4 *result, - GLfloat x, GLfloat y, GLfloat z) -{ - memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); - result->col[3].values[0] = x; - result->col[3].values[1] = y; - result->col[3].values[2] = z; -} - - -#ifdef __cplusplus -static inline GLfloat gluDot4(const GLUvec4 &v1, const GLUvec4 &v2) -{ - return v1.values[0] * v2.values[0] - + v1.values[1] * v2.values[1] - + v1.values[2] * v2.values[2] - + v1.values[3] * v2.values[3]; -} - - -static inline GLfloat gluDot3(const GLUvec4 &v1, const GLUvec4 &v2) -{ - return v1.values[0] * v2.values[0] - + v1.values[1] * v2.values[1] - + v1.values[2] * v2.values[2]; -} - - -static inline GLfloat gluDot2(const GLUvec4 &v1, const GLUvec4 &v2) -{ - return v1.values[0] * v2.values[0] - + v1.values[1] * v2.values[1]; -} - - -inline GLUvec4 GLUvec4::operator+(const GLUvec4 &v) const -{ - return GLUvec4(values[0] + v.values[0], - values[1] + v.values[1], - values[2] + v.values[2], - values[3] + v.values[3]); -} - - -inline GLUvec4 GLUvec4::operator-(const GLUvec4 &v) const -{ - return GLUvec4(values[0] - v.values[0], - values[1] - v.values[1], - values[2] - v.values[2], - values[3] - v.values[3]); -} - - -inline GLUvec4 GLUvec4::operator*(const GLUvec4 &v) const -{ - return GLUvec4(values[0] * v.values[0], - values[1] * v.values[1], - values[2] * v.values[2], - values[3] * v.values[3]); -} - - -inline GLUvec4 GLUvec4::operator*(GLfloat f) const -{ - return GLUvec4(values[0] * f, - values[1] * f, - values[2] * f, - values[3] * f); -} - - -inline GLUvec4 GLUvec4::operator*(const GLUmat4 &m) const -{ - return GLUvec4(gluDot4(*this, m.col[0]), - gluDot4(*this, m.col[1]), - gluDot4(*this, m.col[2]), - gluDot4(*this, m.col[3])); -} - - -inline GLUmat4 GLUmat4::operator+(const GLUmat4 &m) const -{ - GLUmat4 temp; - - gluAdd4m_4m(& temp, this, &m); - return temp; -} - - -inline GLUmat4 GLUmat4::operator-(const GLUmat4 &m) const -{ - return GLUmat4(col[0] - m.col[0], - col[1] - m.col[1], - col[2] - m.col[2], - col[3] - m.col[3]); -} - - -inline GLUmat4 GLUmat4::operator*(GLfloat f) const -{ - GLUmat4 temp; - - gluMult4m_f(& temp, this, f); - return temp; -} - - -inline GLUvec4 GLUmat4::operator*(const GLUvec4 &v) const -{ - return (col[0] * v.values[0]) - + (col[1] * v.values[1]) - + (col[2] * v.values[2]) - + (col[3] * v.values[3]); -} - - -inline GLUmat4 GLUmat4::operator*(const GLUmat4 &m) const -{ - GLUmat4 temp; - - gluMult4m_4m(& temp, this, &m); - return temp; -} - - -#endif /* __cplusplus */ diff --git a/glamor/glu3/matrix.c b/glamor/glu3/matrix.c deleted file mode 100644 index b3d5819f7..000000000 --- a/glamor/glu3/matrix.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright © 2009 Ian D. Romanick - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include "glu3.h" - -#define DEG2RAD(d) ((d) * M_PI / 180.0) - -const GLUmat4 gluIdentityMatrix = { - { - { { 1.0f, 0.0f, 0.0f, 0.0f } }, - { { 0.0f, 1.0f, 0.0f, 0.0f } }, - { { 0.0f, 0.0f, 1.0f, 0.0f } }, - { { 0.0f, 0.0f, 0.0f, 1.0f } } - } -}; - - -void gluTranslate4v(GLUmat4 *result, const GLUvec4 *t) -{ - memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); - result->col[3] = *t; - result->col[3].values[3] = 1.0f; -} - - -void gluScale4v(GLUmat4 *result, const GLUvec4 *t) -{ - memcpy(result, & gluIdentityMatrix, sizeof(gluIdentityMatrix)); - result->col[0].values[0] = t->values[0]; - result->col[1].values[1] = t->values[1]; - result->col[2].values[2] = t->values[2]; -} - - -void gluLookAt4v(GLUmat4 *result, - const GLUvec4 *_eye, - const GLUvec4 *_center, - const GLUvec4 *_up) -{ - static const GLUvec4 col3 = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - const GLUvec4 e = { - { -_eye->values[0], -_eye->values[1], -_eye->values[2], 0.0f } - }; - GLUmat4 translate; - GLUmat4 rotate; - GLUmat4 rotateT; - GLUvec4 f; - GLUvec4 s; - GLUvec4 u; - GLUvec4 center, up; - - center = *_center; - center.values[3] = 0; - up = *_up; - up.values[3] = 0; - - gluAdd4v_4v(& f, ¢er, &e); - gluNormalize4v(& f, & f); - - gluNormalize4v(& u, &up); - - gluCross4v(& s, & f, & u); - gluCross4v(& u, & s, & f); - - rotate.col[0] = s; - rotate.col[1] = u; - rotate.col[2].values[0] = -f.values[0]; - rotate.col[2].values[1] = -f.values[1]; - rotate.col[2].values[2] = -f.values[2]; - rotate.col[2].values[3] = 0.0f; - rotate.col[3] = col3; - gluTranspose4m(& rotateT, & rotate); - - gluTranslate4v(& translate, & e); - gluMult4m_4m(result, & rotateT, & translate); -} - - -void gluRotate4v(GLUmat4 *result, const GLUvec4 *_axis, GLfloat angle) -{ - GLUvec4 axis; - const float c = cos(angle); - const float s = sin(angle); - const float one_c = 1.0 - c; - - float xx; - float yy; - float zz; - - float xs; - float ys; - float zs; - - float xy; - float xz; - float yz; - - /* Only normalize the 3-component axis. A gluNormalize3v might be - * appropriate to save us some computation. - */ - axis = *_axis; - axis.values[3] = 0; - gluNormalize4v(&axis, &axis); - - xx = axis.values[0] * axis.values[0]; - yy = axis.values[1] * axis.values[1]; - zz = axis.values[2] * axis.values[2]; - - xs = axis.values[0] * s; - ys = axis.values[1] * s; - zs = axis.values[2] * s; - - xy = axis.values[0] * axis.values[1]; - xz = axis.values[0] * axis.values[2]; - yz = axis.values[1] * axis.values[2]; - - - result->col[0].values[0] = (one_c * xx) + c; - result->col[0].values[1] = (one_c * xy) + zs; - result->col[0].values[2] = (one_c * xz) - ys; - result->col[0].values[3] = 0.0; - - result->col[1].values[0] = (one_c * xy) - zs; - result->col[1].values[1] = (one_c * yy) + c; - result->col[1].values[2] = (one_c * yz) + xs; - result->col[1].values[3] = 0.0; - - - result->col[2].values[0] = (one_c * xz) + ys; - result->col[2].values[1] = (one_c * yz) - xs; - result->col[2].values[2] = (one_c * zz) + c; - result->col[2].values[3] = 0.0; - - result->col[3].values[0] = 0.0; - result->col[3].values[1] = 0.0; - result->col[3].values[2] = 0.0; - result->col[3].values[3] = 1.0; -} - - -void -gluPerspective4f(GLUmat4 *result, - GLfloat fovy, GLfloat aspect, GLfloat near, GLfloat far) -{ - const double sine = sin(DEG2RAD(fovy / 2.0)); - const double cosine = cos(DEG2RAD(fovy / 2.0)); - const double sine_aspect = sine * aspect; - const double dz = far - near; - - - memcpy(result, &gluIdentityMatrix, sizeof(gluIdentityMatrix)); - if ((sine == 0.0) || (dz == 0.0) || (sine_aspect == 0.0)) { - return; - } - - result->col[0].values[0] = cosine / sine_aspect; - result->col[1].values[1] = cosine / sine; - result->col[2].values[2] = -(far + near) / dz; - result->col[2].values[3] = -1.0; - result->col[3].values[2] = -2.0 * near * far / dz; - result->col[3].values[3] = 0.0; -} - -void gluFrustum6f(GLUmat4 *result, - GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat near, GLfloat far) -{ - memcpy(result, &gluIdentityMatrix, sizeof(gluIdentityMatrix)); - - result->col[0].values[0] = (2.0 * near) / (right - left); - result->col[1].values[1] = (2.0 * near) / (top - bottom); - result->col[2].values[0] = (right + left) / (right - left); - result->col[2].values[1] = (top + bottom) / (top - bottom); - result->col[2].values[2] = -(far + near) / (far - near); - result->col[2].values[3] = -1.0; - result->col[3].values[2] = -2.0 * near * far / (far - near); - result->col[3].values[3] = 0.0; -} - -void gluOrtho6f(GLUmat4 *result, - GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat near, GLfloat far) -{ - memcpy(result, &gluIdentityMatrix, sizeof(gluIdentityMatrix)); - - result->col[0].values[0] = 2.0f / (right - left); - result->col[3].values[0] = -(right + left) / (right - left); - - result->col[1].values[1] = 2.0f / (top - bottom); - result->col[3].values[1] = -(top + bottom) / (top - bottom); - - result->col[2].values[2] = -2.0f / (far - near); - result->col[3].values[2] = -(far + near) / (far - near); -} From f84cc8b84b2944b60eb2a8225e3c44a1cdfb228d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 00:09:38 +0800 Subject: [PATCH 185/462] glamor-ddx: Hardware cursor's format should be GL_RGBA. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor_crtc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 5c2b5c124..959201397 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -494,9 +494,14 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) } glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); #ifdef GLAMOR_GLES2 - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, 64, 64, 0, - GL_BGRA, GL_UNSIGNED_BYTE, image); + /* XXX Actually, the image is BGRA not RGBA, so the r and b + * should be swapped. But as normally, they are the same value + * ignore this currently, don't want to let CPU to do the swizzle. + * considering to put this function to the glamor rendering directory. + * Thus we can reuse the shader to do this.*/ + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image); #else glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, From 504e03c0b59f4dc3b8058abdce79706a72cd0dde Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 00:17:58 +0800 Subject: [PATCH 186/462] glamor: GLES2 doesn't support GL_CLAMP_TO_BORDER. Simply comments it out. Need revisit latter. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6099af744..cec6c8d25 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -376,11 +376,11 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); switch (picture->repeatType) { case RepeatNone: -#ifdef GLAMOR_GLES2 - assert(1); -#endif +#ifndef GLAMOR_GLES2 + /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); +#endif break; case RepeatNormal: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); @@ -407,8 +407,9 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; } - +#ifndef GLAMOR_GLES2 glEnable(GL_TEXTURE_2D); +#endif } static void @@ -1037,10 +1038,12 @@ glamor_composite_with_shader(CARD8 op, glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); REGION_UNINIT(dst->pDrawable->pScreen, ®ion); glDisable(GL_BLEND); +#ifndef GLAMOR_GLES2 glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); +#endif glUseProgram(0); if (saved_source_format) source->format = saved_source_format; From 0eea084db54fb88b9933fd1326a2b0b059b3f9d7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 00:20:01 +0800 Subject: [PATCH 187/462] glamor: GLES2 doesn't support glEnable/Disable Texture 2D. Signed-off-by: Zhigang Gong --- glamor/glamor_tile.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 5104f0b47..25ad63583 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -140,9 +140,11 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +#ifndef GLAMOR_GLES2 glEnable(GL_TEXTURE_2D); +#endif glamor_set_normalize_tcoords(src_xscale, src_yscale, tile_x1, tile_y1, tile_x2, tile_y2, @@ -170,7 +172,9 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#ifndef GLAMOR_GLES2 glDisable(GL_TEXTURE_2D); +#endif } glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glUseProgram(0); From 67da52ec13a87846201a99d5a31db28668d9fdfd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 00:21:09 +0800 Subject: [PATCH 188/462] glamor: Add color conversion support by using new shader. There are two places we need to do color conversion. 1. When upload a image data to a texture. 2. When download a texture to a memory buffer. As the color format may not be supported in GLES2. We may need to do the following two operations to convert dat. a. revert argb to bgra / abgr to rgba. b. swap argb to abgr / bgra to rgba. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 52 +++++++++++- glamor/glamor_fill.c | 1 - glamor/glamor_pixmap.c | 179 ++++++++++++++++++++++++++++++--------- glamor/glamor_priv.h | 132 ++++++++++++++++++++++++++++- glamor/glamor_putimage.c | 29 +++---- glamor/glamor_setspans.c | 11 ++- 6 files changed, 339 insertions(+), 65 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 9f0457380..d4588e28a 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -133,7 +133,6 @@ Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - return glamor_download_pixmap_to_cpu(pixmap, access); } @@ -154,17 +153,47 @@ glamor_init_finish_access_shaders(ScreenPtr screen) const char *fs_source = "varying vec2 source_texture;\n" "uniform sampler2D sampler;\n" + "uniform int no_revert;" + "uniform int swap_rb;" "void main()\n" "{\n" - " gl_FragColor = texture2D(sampler, source_texture);\n" + " if (no_revert == 1) \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = texture2D(sampler, source_texture).bgra;\n" + " else \n" + " gl_FragColor = texture2D(sampler, source_texture).rgba;\n" + " } \n" + " else \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = texture2D(sampler, source_texture).argb;\n" + " else \n" + " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" + " } \n" "}\n"; const char *set_alpha_source = "varying vec2 source_texture;\n" "uniform sampler2D sampler;\n" + "uniform int no_revert;" + "uniform int swap_rb;" "void main()\n" "{\n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" + " if (no_revert == 1) \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" + " else \n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" + " } \n" + " else \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" + " else \n" + " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" + " } \n" "}\n"; GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; GLint sampler_uniform_location; @@ -190,17 +219,31 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]); + glamor_priv->finish_access_no_revert[0] = + glGetUniformLocation(glamor_priv->finish_access_prog[0], "no_revert"); + + glamor_priv->finish_access_swap_rb[0] = + glGetUniformLocation(glamor_priv->finish_access_prog[0], "swap_rb"); sampler_uniform_location = glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); glUseProgram(glamor_priv->finish_access_prog[0]); glUniform1i(sampler_uniform_location, 0); + glUniform1i(glamor_priv->finish_access_no_revert[0],1); + glUniform1i(glamor_priv->finish_access_swap_rb[0],0); glUseProgram(0); + glamor_priv->finish_access_no_revert[1] = + glGetUniformLocation(glamor_priv->finish_access_prog[1], "no_revert"); + glamor_priv->finish_access_swap_rb[1] = + glGetUniformLocation(glamor_priv->finish_access_prog[1], "swap_rb"); sampler_uniform_location = glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); glUseProgram(glamor_priv->finish_access_prog[1]); + glUniform1i(glamor_priv->finish_access_no_revert[1],1); glUniform1i(sampler_uniform_location, 0); + glUniform1i(glamor_priv->finish_access_swap_rb[1],0); glUseProgram(0); + } void @@ -224,8 +267,9 @@ glamor_finish_access(DrawablePtr drawable) pixmap_priv->pbo_valid = FALSE; glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; - } else + } else { free(pixmap->devPrivate.ptr); + } pixmap->devPrivate.ptr = NULL; } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 660ffe014..873f383a5 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -143,7 +143,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat color[4]; float vertices[8]; GLfloat xscale, yscale; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("dest %p has no fbo.\n", pixmap); goto fail; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 1dc1ee93c..1e17069f1 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -83,12 +83,15 @@ glamor_validate_pixmap(PixmapPtr pixmap) void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { - glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); -#ifndef GLAMOR_GLES2 - glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); glLoadIdentity(); -#endif +// glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glamor_pixmap_ensure_fb(pixmap_priv->container); +#ifndef GLAMOR_GLES2 + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +#endif glViewport(0, 0, pixmap_priv->container->drawable.width, pixmap_priv->container->drawable.height); @@ -199,7 +202,7 @@ glamor_set_alu(unsigned char alu) * Upload pixmap to a specified texture. * This texture may not be the one attached to it. **/ - +int in_restore = 0; static void __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, GLuint tex) { @@ -225,7 +228,6 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { iformat = format; - type = GL_UNSIGNED_BYTE; } stride = pixmap->devKind; @@ -264,7 +266,8 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, static void _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, int no_alpha, int flip) + GLenum type, int no_alpha, int no_revert, + int flip) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -290,8 +293,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ - - if (no_alpha == 0 && !need_flip) { + if (no_alpha == 0 && no_revert == 1 && !need_flip) { __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->tex); return; } @@ -303,14 +305,6 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, ptexcoords = texcoords_inv; /* Slow path, we need to flip y or wire alpha to 1. */ -#if 0 - 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); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); @@ -319,10 +313,8 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, 2 * sizeof(float), ptexcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); -#endif - glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); glGenTextures(1, &tex); __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); @@ -331,12 +323,18 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +#ifndef GLAMOR_GLES2 glEnable(GL_TEXTURE_2D); +#endif glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); + glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],0); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +#ifndef GLAMOR_GLES2 glDisable(GL_TEXTURE_2D); +#endif glUseProgram(0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); @@ -386,7 +384,7 @@ glamor_pixmap_ensure_fb(PixmapPtr pixmap) * 2. no_alpha != 0, we need to wire the alpha. * */ static int -glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha) +glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) { int need_fbo; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -402,7 +400,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha) if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return 0; - if (no_alpha != 0 || !glamor_priv->yInverted) + if (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) need_fbo = 1; else need_fbo = 0; @@ -427,16 +425,17 @@ enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap) { GLenum format, type; - int no_alpha; + int no_alpha, no_revert; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &no_alpha)) { + &no_alpha, + &no_revert)) { glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); return GLAMOR_UPLOAD_FAILED; } - if (glamor_pixmap_upload_prepare(pixmap, no_alpha)) + if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) return GLAMOR_UPLOAD_FAILED; glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD, "Uploading pixmap %p %dx%d depth%d.\n", @@ -444,7 +443,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth); - _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, 1); + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, no_revert, 1); return GLAMOR_UPLOAD_DONE; } @@ -468,18 +467,101 @@ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap) { GLenum format, type; - int no_alpha; + int no_alpha, no_revert; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &no_alpha)) { + &no_alpha, + &no_revert)) { ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); assert(0); } - _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, 1); + + in_restore = 1; + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, no_revert, 1); + in_restore = 0; } +/* + * as gles2 only support a very small set of color format and + * type when do glReadPixel, + * Before we use glReadPixels to get back a textured pixmap, + * Use shader to convert it to a supported format and thus + * get a new temporary pixmap returned. + * */ + +PixmapPtr +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, + GLenum *type, int no_alpha, int no_revert) +{ + glamor_pixmap_private *source_priv; + glamor_screen_private *glamor_priv; + ScreenPtr screen; + PixmapPtr temp_pixmap; + glamor_pixmap_private *temp_pixmap_priv; + static float vertices[8] = {-1, -1, + 1, -1, + 1, 1, + -1, 1}; + static float texcoords[8] = {0, 0, + 1, 0, + 1, 1, + 0, 1}; + + int swap_rb = 0; + + screen = source->drawable.pScreen; + + glamor_priv = glamor_get_screen_private(screen); + source_priv = glamor_get_pixmap_private(source); + if (*format == GL_BGRA) { + *format = GL_RGBA; + swap_rb = 1; + } + + + temp_pixmap = (*screen->CreatePixmap)(screen, + source->drawable.width, + source->drawable.height, + source->drawable.depth, + 0); + + temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + + glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + glTexImage2D(GL_TEXTURE_2D, 0, *format, source->drawable.width, + source->drawable.height, 0, + *format, *type, NULL); + + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + vertices); + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + + glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + texcoords); + glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, source_priv->tex); + + glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); + + glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); + glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glUseProgram(0); + glFlush(); + return temp_pixmap; +} + /** * Move a pixmap to CPU memory. @@ -497,18 +579,21 @@ 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 no_alpha; + int no_alpha, no_revert; uint8_t *data = NULL, *read; + PixmapPtr temp_pixmap = NULL; + ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - - + + screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &no_alpha)) { + &no_alpha, + &no_revert)) { ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); assert(0); // Should never happen. return FALSE; @@ -521,13 +606,21 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth); - + stride = pixmap->devKind; + glamor_set_destination_pixmap_priv_nc(pixmap_priv); /* XXX we may don't need to validate it on GPU here, * we can just validate it on CPU. */ glamor_validate_pixmap(pixmap); - switch (access) { + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) || no_revert != 1)) { + + temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, &type, no_alpha, no_revert); + + } + switch (access) { case GLAMOR_ACCESS_RO: gl_access = GL_READ_ONLY; gl_usage = GL_STREAM_READ; @@ -544,9 +637,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) ErrorF("Glamor: Invalid access code. %d\n", access); assert(0); } - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { data = malloc(stride * pixmap->drawable.height); + } row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, row_length); @@ -582,8 +677,10 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); } else { + if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) + type = GL_UNSIGNED_SHORT_5_5_5_1; glReadPixels (0, 0, - row_length, pixmap->drawable.height, + pixmap->drawable.width, pixmap->drawable.height, format, type, data); } } else { @@ -614,6 +711,12 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glBindFramebuffer(GL_FRAMEBUFFER, 0); done: pixmap->devPrivate.ptr = data; + + if (temp_pixmap) { + glFlush(); + (*screen->DestroyPixmap)(temp_pixmap); + } + return TRUE; } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 400988574..1f3e8c464 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -43,6 +43,7 @@ #define GL_UNSIGNED_INT_8_8_8_8 0x8035 #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 @@ -236,6 +237,8 @@ typedef struct glamor_screen_private { /* glamor_finishaccess */ GLint finish_access_prog[2]; + GLint finish_access_no_revert[2]; + GLint finish_access_swap_rb[2]; /* glamor_solid */ GLint solid_prog; @@ -408,13 +411,16 @@ format_for_pixmap(PixmapPtr pixmap) * * Return 0 if find a matched texture type. Otherwise return -1. **/ +#ifndef GLAMOR_GLES2 static inline int glamor_get_tex_format_type_from_pictformat(PictFormatShort format, GLenum *tex_format, GLenum *tex_type, - int *no_alpha) + int *no_alpha, + int *no_revert) { *no_alpha = 0; + *no_revert = 1; switch (format) { case PICT_a1: *tex_format = GL_COLOR_INDEX; @@ -497,13 +503,125 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, } return 0; } +#else +#define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) + +static inline int +glamor_get_tex_format_type_from_pictformat(PictFormatShort format, + GLenum *tex_format, + GLenum *tex_type, + int *no_alpha, + int *no_revert) +{ + *no_alpha = 0; + *no_revert = IS_LITTLE_ENDIAN; + + switch (format) { + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_BYTE; + *no_revert = !IS_LITTLE_ENDIAN; + break; + + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_BYTE; + break; + + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + break; + + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_10_10_10_2; + *no_revert = TRUE; + break; + + case PICT_x2b10g10r10: + *no_alpha = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_10_10_10_2; + *no_revert = TRUE; + break; + + case PICT_r5g6b5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *no_revert = TRUE; + break; + + case PICT_b5g6r5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *no_revert = FALSE; + break; + + case PICT_x1b5g5r5: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + *no_revert = TRUE; + break; + + case PICT_x1r5g5b5: + *no_alpha = 1; + case PICT_a1r5g5b5: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + *no_revert = TRUE; + break; + + case PICT_a8: + *tex_format = GL_ALPHA; + *tex_type = GL_UNSIGNED_BYTE; + *no_revert = TRUE; + break; + + case PICT_x4r4g4b4: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + *no_revert = TRUE; + break; + + case PICT_x4b4g4r4: + *no_alpha = 1; + case PICT_a4b4g4r4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + *no_revert = TRUE; + break; + + default: + LogMessageVerb(X_INFO, 0, "fail to get matched format for %x \n", format); + return -1; + } + return 0; +} + + +#endif static inline int glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type, - int *ax) + int *no_alpha, + int *no_revert) { glamor_pixmap_private *pixmap_priv; PictFormatShort pict_format; @@ -515,7 +633,8 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, pict_format = format_for_depth(pixmap->drawable.depth); return glamor_get_tex_format_type_from_pictformat(pict_format, - format, type, ax); + format, type, + no_alpha, no_revert); } @@ -658,6 +777,11 @@ int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv); * */ void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv); + +PixmapPtr +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, + GLenum *type, int no_alpha, int no_revert); + void glamor_set_alu(unsigned char alu); Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); void glamor_get_transform_uniform_locations(GLint prog, @@ -870,7 +994,7 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -#define GLAMOR_DELAYED_FILLING +//#define GLAMOR_DELAYED_FILLING #include"glamor_utils.h" diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index addfdf2bd..a7a6186ee 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -265,7 +265,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, float vertices[8], texcoords[8]; GLfloat xscale, yscale, txscale, tyscale; GLuint tex; - int no_alpha; + int no_alpha, no_revert; if (image_format == XYBitmap) { assert(depth == 1); goto fail; @@ -290,7 +290,8 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &no_alpha + &no_alpha, + &no_revert )) { glamor_fallback("unknown depth. %d \n", drawable->depth); @@ -300,14 +301,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, /* XXX consider to reuse a function to do the following work. */ glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); -#if 0 - glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices); - glEnableClientState(GL_VERTEX_ARRAY); - - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -#else glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); @@ -317,7 +310,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, 2 * sizeof(float), texcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); -#endif if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -333,20 +325,25 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - type = GL_UNSIGNED_BYTE; iformat = format; } else { iformat = GL_RGBA; } + glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +#ifndef GLAMOR_GLES2 glEnable(GL_TEXTURE_2D); +#endif glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); + glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], 0); x += drawable->x; y += drawable->y; @@ -394,7 +391,9 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } +#ifndef GLAMOR_GLES2 glDisable(GL_TEXTURE_2D); +#endif glUseProgram(0); glDisableVertexAttribArray(GLAMOR_VERTEX_POS); glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); @@ -409,9 +408,9 @@ fail: glamor_set_planemask(pixmap, ~0); 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, + if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { + fbPutImage(&pixmap->drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); - glamor_finish_access(drawable); + glamor_finish_access(&pixmap->drawable); } } diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index a1d5dc1a6..8b2676b4b 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -38,7 +38,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); glamor_screen_private *glamor_priv; GLenum format, type; - int no_alpha, i; + int no_alpha, no_revert, i; uint8_t *drawpixels_src = (uint8_t *)src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; @@ -46,18 +46,23 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + glamor_fallback("ES2 fallback.\n"); goto fail; + } if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, &format, &type, - &no_alpha + &no_alpha, + &no_revert )) { glamor_fallback("unknown depth. %d \n", drawable->depth); goto fail; } + + if (glamor_set_destination_pixmap(dest_pixmap)) goto fail; From 1f129c491bfc825465c3bc0e9b745b7f66dea720 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 00:32:57 +0800 Subject: [PATCH 189/462] glamor: Convert pixmap to supported format before getspans. Signed-off-by: Zhigang Gong --- glamor/glamor_getspans.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index e1a20baef..ba409dc23 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -41,9 +41,10 @@ glamor_get_spans(DrawablePtr drawable, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - int no_alpha; + int no_alpha, no_revert; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + PixmapPtr temp_pixmap = NULL; int i; uint8_t *readpixels_dst = (uint8_t *)dst; int x_off, y_off; @@ -56,7 +57,8 @@ glamor_get_spans(DrawablePtr drawable, if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, - &no_alpha + &no_alpha, + &no_revert )) { glamor_fallback("unknown depth. %d \n", drawable->depth); @@ -65,7 +67,15 @@ glamor_get_spans(DrawablePtr drawable, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); - + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + /* XXX prepare whole pixmap is not efficient. */ + temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, + &type, no_alpha, no_revert); + pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + } + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); for (i = 0; i < count; i++) { if (glamor_priv->yInverted) { @@ -85,6 +95,8 @@ glamor_get_spans(DrawablePtr drawable, } readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } + if (temp_pixmap) + pixmap->drawable.pScreen->DestroyPixmap(temp_pixmap); return; fail: From 1658454dea4330144ebc0b02e1b42feed6db4f41 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 00:33:35 +0800 Subject: [PATCH 190/462] glamor: Fix the copy of overlaped region in one pixmap. Originaly, we use fbo blit to handle overlaped region copy. But GLES2 doesn't support that, just simply copy the needed region to another texture can fix this problem. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 1e160acb6..3e6e6b9fc 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -124,7 +124,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, BoxPtr box, int nbox, int dx, - int dy) + int dy + ) { glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pScreen); @@ -193,7 +194,9 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); +#ifndef GLAMOR_GLES2 glEnable(GL_TEXTURE_2D); +#endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -202,6 +205,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, texcoords); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glUseProgram(glamor_priv->finish_access_prog[0]); + glUniform1i(glamor_priv->finish_access_no_revert[0], 1); + glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); } else { @@ -231,7 +236,9 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glDisableVertexAttribArray(GLAMOR_VERTEX_POS); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); +#ifndef GLAMOR_GLES2 glDisable(GL_TEXTURE_2D); +#endif } glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ @@ -308,23 +315,29 @@ glamor_copy_n_to_n(DrawablePtr src, #endif glamor_calculate_boxes_bound(&bound, box, nbox); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) + /* Overlaped indicate the src and dst are the same pixmap. */ + if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) - * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height)) { + * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height))) { temp_pixmap = (*screen->CreatePixmap)(screen, bound.x2 - bound.x1, bound.y2 - bound.y1, src_pixmap->drawable.depth, - GLAMOR_CREATE_PIXMAP_CPU); + overlaped ? 0 : GLAMOR_CREATE_PIXMAP_CPU); if (!temp_pixmap) goto fail; glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); temp_src = &temp_pixmap->drawable; - fbCopyNtoN(src, temp_src, gc, box, nbox, - temp_dx + bound.x1, temp_dy + bound.y1, - reverse, upsidedown, bitplane, - closure); + + if (overlaped) + glamor_copy_n_to_n_textured(src, temp_src, gc, box, nbox, + temp_dx + bound.x1, temp_dy + bound.y1); + else + fbCopyNtoN(src, temp_src, gc, box, nbox, + temp_dx + bound.x1, temp_dy + bound.y1, + reverse, upsidedown, bitplane, + closure); glamor_transform_boxes(box, nbox, bound.x1, bound.y1); temp_dx = -bound.x1; temp_dy = -bound.y1; From eaa07998c432f68485423c4d108220ce1d72e7b6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 16 Aug 2011 14:05:25 +0800 Subject: [PATCH 191/462] glamor: Add device independent glamor to the installation package. Other ddx driver may link libglamor_dix to utilize glamor. Signed-off-by: Zhigang Gong --- configure.ac | 10 +++++++++- glamor/Makefile.am | 12 +++++++++--- hw/xfree86/dixmods/Makefile.am | 8 +++++++- hw/xfree86/glamor/Makefile.am | 10 +++------- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 69b1ac3c5..d67e7cb10 100644 --- a/configure.ac +++ b/configure.ac @@ -801,7 +801,8 @@ LIBUDEV="libudev >= 143" LIBSELINUX="libselinux >= 2.0.86" LIBDBUS="dbus-1 >= 1.0" LIBPIXMAN="pixman-1 >= 0.21.8" - +LIBEGL="egl >= 7.12.0" +LIBGLESV2="glesv2 >= 7.11.0" dnl Pixman is always required, but we separate it out so we can link dnl specific modules against it PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) @@ -1779,14 +1780,21 @@ GLAMOR=yes if test "x$GLAMOR" = xyes; then AC_DEFINE(GLAMOR,1,[Build Glamor]) + if test "x$GLAMOR_GLES2" = xyes; then AC_DEFINE(GLAMOR_GLES2,1,[Build glamor over GLES2]) + PKG_CHECK_MODULES(GLESV2, $LIBGLESV2) + REQUIRED_LIBS="$REQUIRED_LIBS $LIBGLESV2" else AC_DEFINE(GLAMOR_GL,1,[Build glamor over GL]) + PKG_CHECK_MODULES(GL, $LIBGL) + REQUIRED_LIBS="$REQUIRED_LIBS $LIBGL" fi if test "x$GLAMOR_DDX" = xyes; then AC_DEFINE(GLAMOR_DDX,1,[Enable glamor ddx driver]) + PKG_CHECK_MODULES(EGL, $LIBEGL) + REQUIRED_LIBS="$REQUIRED_LIBS $LIBEGL" fi fi diff --git a/glamor/Makefile.am b/glamor/Makefile.am index ec38ac4e8..fcde76503 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -9,13 +9,20 @@ sdk_HEADERS = glamor.h endif if GLAMOR_GLES2 -GLAMOR_GLES2_CFLAGS = -DGLAMOR_GLES2 +libglamor_la_LIBADD = $(GLESV2_LIBS) +else +libglamor_la_LIBADD = $(GL_LIBS) +endif + +if XORG +sdk_HEADERS = glamor.h endif INCLUDES = \ $(XORG_INCS) -AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(GLAMOR_GLES2_CFLAGS) $(LIBDRM_CFLAGS) + +AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ @@ -37,4 +44,3 @@ libglamor_la_SOURCES = \ glamor_picture.c\ glamor_window.c\ glamor.h - diff --git a/hw/xfree86/dixmods/Makefile.am b/hw/xfree86/dixmods/Makefile.am index 1a162ab1c..6dc63ceb7 100644 --- a/hw/xfree86/dixmods/Makefile.am +++ b/hw/xfree86/dixmods/Makefile.am @@ -16,7 +16,8 @@ endif module_LTLIBRARIES = libfb.la \ libwfb.la \ - libshadow.la + libshadow.la \ + libglamor_dix.la extsmoduledir = $(moduledir)/extensions extsmodule_LTLIBRARIES = $(RECORDMOD) \ @@ -34,6 +35,11 @@ libdbe_la_LDFLAGS = -avoid-version libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la libdbe_la_SOURCES = dbemodule.c +libglamor_dix_la_LDFLAGS = -avoid-version +libglamor_dix_la_LIBADD = $(top_builddir)/glamor/libglamor.la +libglamor_dix_la_SOURCES = +libglamor_dix_la_CFLAGS = $(AM_CFLAGS) + libfb_la_LDFLAGS = -avoid-version libfb_la_LIBADD = $(top_builddir)/fb/libfb.la libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index dcd44b2d8..8432645ca 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -13,15 +13,11 @@ glamor_la_CFLAGS = \ if GLAMOR_GLES2 glamor_la_CFLAGS+=-DGLAMOR_GLES2 -GLAMOR_GL_LIB = -lGLESv2 -else -GLAMOR_GL_LIB = -lGL endif -glamor_la_LDFLAGS = \ - -module -avoid-version -L$(libdir) -lEGL \ - $(top_builddir)/glamor/libglamor.la \ - -L$(libdir)/../lib64 $(GLAMOR_GL_LIB) +glamor_la_LDFLAGS = -module -avoid-version \ + $(top_builddir)/glamor/libglamor.la \ + $(EGL_LIBS) glamor_ladir = $(moduledir)/drivers glamor_la_SOURCES = \ From 3648e35b5d0ffcb2ea5d40c842a7f8dd39b27b50 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 19 Aug 2011 10:53:44 +0800 Subject: [PATCH 192/462] glamor-ddx: Add code to check required egl extensions. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 317342b13..3ac003dc2 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -304,6 +304,31 @@ glamor_close_screen_ddx(int scrnIndex, ScreenPtr screen) return TRUE; } + + +static Bool +glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) +{ + const char *egl_extensions; + char *pext; + int ext_len; + ext_len = strlen(extension); + + egl_extensions = (const char*)eglQueryString(glamor->display, EGL_EXTENSIONS); + pext = (char*)egl_extensions; + + if (pext == NULL || extension == NULL) + return FALSE; + while((pext = strstr(pext, extension)) != NULL) { + if (pext[ext_len] == ' ' || pext[ext_len] == '\0') + return TRUE; + pext += ext_len; + } + return FALSE; +} + + + static Bool glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) { @@ -353,6 +378,20 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) version = eglQueryString(glamor->display, EGL_VERSION); xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); +#define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ + if (!glamor_egl_has_extension(glamor, "EGL_" #EXT)) { \ + ErrorF("EGL_" #EXT "required.\n"); \ + return FALSE; \ + } + + GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); + GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); +#ifdef GLAMOR_GLES2 + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_gles2); +#else + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); +#endif + glamor->egl_create_drm_image_mesa = (PFNEGLCREATEDRMIMAGEMESA)eglGetProcAddress("eglCreateDRMImageMESA"); glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA)eglGetProcAddress("eglExportDRMImageMESA"); From 52cce9333fed2035da9623f338428a5d220b577d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 19 Aug 2011 11:05:21 +0800 Subject: [PATCH 193/462] glamor: egl version 7.11 should be ok for us. Signed-off-by: Zhigang Gong --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d67e7cb10..25e9dd362 100644 --- a/configure.ac +++ b/configure.ac @@ -801,7 +801,7 @@ LIBUDEV="libudev >= 143" LIBSELINUX="libselinux >= 2.0.86" LIBDBUS="dbus-1 >= 1.0" LIBPIXMAN="pixman-1 >= 0.21.8" -LIBEGL="egl >= 7.12.0" +LIBEGL="egl >= 7.11.0" LIBGLESV2="glesv2 >= 7.11.0" dnl Pixman is always required, but we separate it out so we can link dnl specific modules against it From ef3ea0f46bf1b688249cd37d54cfa67ec55041b0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 19 Aug 2011 11:06:56 +0800 Subject: [PATCH 194/462] glamor: Don't need to check status when set the target. As we already checked the status when create the fbo. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 1e17069f1..15fc01448 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -83,9 +83,7 @@ glamor_validate_pixmap(PixmapPtr pixmap) void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { -// glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - - glamor_pixmap_ensure_fb(pixmap_priv->container); + glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); #ifndef GLAMOR_GLES2 glMatrixMode(GL_PROJECTION); glLoadIdentity(); From 65812b538f23bfccc32a7bbc0b2c4e93e1cd8fe8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 23 Aug 2011 10:31:50 +0800 Subject: [PATCH 195/462] glamor-dix: Make a glamor dix module. And modify the header file to export three APIs to the ddx driver. Signed-off-by: Zhigang Gong --- configure.ac | 6 ++-- glamor/glamor.h | 6 ++-- hw/xfree86/dixmods/Makefile.am | 12 +++++--- hw/xfree86/dixmods/glamor_module.c | 47 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 hw/xfree86/dixmods/glamor_module.c diff --git a/configure.ac b/configure.ac index 25e9dd362..2a1c7869d 100644 --- a/configure.ac +++ b/configure.ac @@ -646,7 +646,7 @@ AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest serv AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) -#AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor server (default: no)]), [GLAMOR=$enableval], [GLAMOR=no]) +AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no]) AC_ARG_ENABLE(glamor-ddx, AS_HELP_STRING([--enable-glamor-ddx], [Build glamor ddx (default: no)]), [GLAMOR_DDX=$enableval], [GLAMOR_DDX=no]) dnl kdrive and its subsystems AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) @@ -1772,12 +1772,10 @@ AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) dnl glamor -AM_CONDITIONAL([GLAMOR], [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes]) +AM_CONDITIONAL([GLAMOR], [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes || test "x$GLAMOR" = xyes]) AM_CONDITIONAL([GLAMOR_GLES2], [test "x$GLAMOR_GLES2" = xyes]) AM_CONDITIONAL([GLAMOR_DDX], [test "x$GLAMOR_DDX" = xyes]) -GLAMOR=yes - if test "x$GLAMOR" = xyes; then AC_DEFINE(GLAMOR,1,[Build Glamor]) diff --git a/glamor/glamor.h b/glamor/glamor.h index 2c1b241ba..25f4506d2 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -43,6 +43,6 @@ #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_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); +extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); +extern _X_EXPORT void glamor_fini(ScreenPtr screen); +extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); diff --git a/hw/xfree86/dixmods/Makefile.am b/hw/xfree86/dixmods/Makefile.am index 6dc63ceb7..84c909b9c 100644 --- a/hw/xfree86/dixmods/Makefile.am +++ b/hw/xfree86/dixmods/Makefile.am @@ -14,10 +14,14 @@ if RECORD RECORDMOD = librecord.la endif +if GLAMOR +LIBGLAMOR_DIX = libglamor_dix.la +endif + module_LTLIBRARIES = libfb.la \ libwfb.la \ libshadow.la \ - libglamor_dix.la + $(LIBGLAMOR_DIX) extsmoduledir = $(moduledir)/extensions extsmodule_LTLIBRARIES = $(RECORDMOD) \ @@ -34,12 +38,12 @@ INCLUDES = @XORG_INCS@ \ libdbe_la_LDFLAGS = -avoid-version libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la libdbe_la_SOURCES = dbemodule.c - +if GLAMOR libglamor_dix_la_LDFLAGS = -avoid-version libglamor_dix_la_LIBADD = $(top_builddir)/glamor/libglamor.la -libglamor_dix_la_SOURCES = +libglamor_dix_la_SOURCES = glamor_module.c libglamor_dix_la_CFLAGS = $(AM_CFLAGS) - +endif libfb_la_LDFLAGS = -avoid-version libfb_la_LIBADD = $(top_builddir)/fb/libfb.la libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c diff --git a/hw/xfree86/dixmods/glamor_module.c b/hw/xfree86/dixmods/glamor_module.c new file mode 100644 index 000000000..ee2dba871 --- /dev/null +++ b/hw/xfree86/dixmods/glamor_module.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 1998 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86Module.h" + +static XF86ModuleVersionInfo VersRec = +{ + "glamor_dix", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_ANSIC, /* Only need the ansic layer */ + ABI_ANSIC_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} /* signature, to be patched into the file by a tool */ +}; + +_X_EXPORT XF86ModuleData glamor_dixModuleData = { &VersRec, NULL, NULL }; From bd0ea43f3999e29ae5953ca5257b1795916dd5e7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 23 Aug 2011 13:27:48 +0800 Subject: [PATCH 196/462] glamor: Change to use the original drawable in glamor_fill. As glamor_fill may fallback to software rasterization, we'd better to use the original drawable as input paramter. Signed-off-by: Zhigang Gong --- glamor/glamor_fill.c | 19 +++++++++++-------- glamor/glamor_fillspans.c | 6 +----- glamor/glamor_polyfillrect.c | 7 ++----- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 873f383a5..cbd2b59f6 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -41,12 +41,15 @@ glamor_fill(DrawablePtr drawable, int height) { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); + int off_x, off_y; + + glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y); switch (gc->fillStyle) { case FillSolid: if (!glamor_solid(dst_pixmap, - x, - y, + x + off_x, + y + off_y, width, height, gc->alu, @@ -58,8 +61,8 @@ glamor_fill(DrawablePtr drawable, case FillOpaqueStippled: if (!glamor_stipple(dst_pixmap, gc->stipple, - x, - y, + x + off_x, + y + off_y, width, height, gc->alu, @@ -74,14 +77,14 @@ glamor_fill(DrawablePtr drawable, case FillTiled: if (!glamor_tile(dst_pixmap, gc->tile.pixmap, - x, - y, + x + off_x, + y + off_y, width, height, gc->alu, gc->planemask, - drawable->x + x - gc->patOrg.x, - drawable->y + y - gc->patOrg.y)) + drawable->x + x + off_x - gc->patOrg.x, + drawable->y + y + off_y - gc->patOrg.y)) goto fail; break; } diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index b1f79a9d8..9a97da250 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -42,15 +42,11 @@ glamor_fill_spans(DrawablePtr drawable, int nbox; BoxPtr pbox; int x1, x2, y; - int off_x, off_y; RegionPtr pClip = fbGetCompositeClip(gc); - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; - glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); ppt = points; while (n--) { x1 = ppt->x; @@ -74,7 +70,7 @@ glamor_fill_spans(DrawablePtr drawable, if (x2 <= x1) continue; glamor_fill (drawable,gc, - x1 + off_x, y + off_y, + x1, y, x2 - x1 , 1); pbox++; } diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 218c308dd..3cc4b527d 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -47,16 +47,13 @@ glamor_poly_fill_rect(DrawablePtr drawable, int xorg, yorg; int n; register BoxPtr pbox; - int off_x, off_y; RegionPtr pClip = fbGetCompositeClip(gc); - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { goto fail; } xorg = drawable->x; yorg = drawable->y; - glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); while (nrect--) { fullX1 = prect->x + xorg; @@ -92,8 +89,8 @@ glamor_poly_fill_rect(DrawablePtr drawable, continue; glamor_fill(drawable, gc, - x1 + off_x, - y1 + off_y, + x1, + y1, x2 - x1, y2 - y1); } From b4f265c7f9bcb7824df19ea915ab32fe84d9ec53 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 23 Aug 2011 13:30:54 +0800 Subject: [PATCH 197/462] glamor: Fallback to software fb when repeat is needed. Need to be fixed latter. We should not need any fallback here. But currently, the implementation for repeating tiling is broken. Signed-off-by: Zhigang Gong --- glamor/glamor_tile.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 25ad63583..8fe4b3891 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -98,10 +98,14 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; - src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); + if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) + || ((tile_y != 0) && (tile_y + height > tile->drawable.height))) { + ErrorF("tile_x = %d tile_y = %d \n", tile_x, tile_y); + goto fail; + } if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; From 54c91079d2bd21d3fd97b6d5fa3ba5c4a86b6337 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 23 Aug 2011 14:04:07 +0800 Subject: [PATCH 198/462] glamor-gles2: Add explicit precision qualifiers for gles2. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 10 ++++++---- glamor/glamor_fill.c | 1 + glamor/glamor_priv.h | 7 ++++++- glamor/glamor_render.c | 10 ++++++++++ glamor/glamor_tile.c | 1 + 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index d4588e28a..3609600bc 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -151,10 +151,11 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "}\n"; const char *fs_source = + GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D sampler;\n" - "uniform int no_revert;" - "uniform int swap_rb;" + "uniform int no_revert;\n" + "uniform int swap_rb;\n" "void main()\n" "{\n" " if (no_revert == 1) \n" @@ -174,10 +175,11 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "}\n"; const char *set_alpha_source = + GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D sampler;\n" - "uniform int no_revert;" - "uniform int swap_rb;" + "uniform int no_revert;\n" + "uniform int swap_rb;\n" "void main()\n" "{\n" " if (no_revert == 1) \n" diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index cbd2b59f6..0b3d5fddf 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -112,6 +112,7 @@ glamor_init_solid_shader(ScreenPtr screen) " gl_Position = v_position;\n" "}\n"; const char *solid_fs = + GLAMOR_DEFAULT_PRECISION "uniform vec4 color;\n" "void main()\n" "{\n" diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1f3e8c464..4feb0048e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -36,7 +36,6 @@ #include "glamor.h" #ifdef GLAMOR_GLES2 - #define GL_BGRA GL_BGRA_EXT #define GL_COLOR_INDEX 0x1900 #define GL_BITMAP 0x1A00 @@ -77,9 +76,15 @@ #ifdef GLAMOR_GLES2 #include #include + +#define GLAMOR_DEFAULT_PRECISION \ + "precision mediump float;\n" + #else #include #include + +#define GLAMOR_DEFAULT_PRECISION #endif diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index cec6c8d25..bc6347883 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -71,12 +71,14 @@ static GLuint glamor_create_composite_fs(struct shader_key *key) { const char *source_solid_fetch = + GLAMOR_DEFAULT_PRECISION "uniform vec4 source;\n" "vec4 get_source()\n" "{\n" " return source;\n" "}\n"; const char *source_alpha_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" @@ -84,6 +86,7 @@ glamor_create_composite_fs(struct shader_key *key) " return texture2D(source_sampler, source_texture);\n" "}\n"; const char *source_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" @@ -91,12 +94,14 @@ glamor_create_composite_fs(struct shader_key *key) " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" "}\n"; const char *mask_solid_fetch = + GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" "vec4 get_mask()\n" "{\n" " return mask;\n" "}\n"; const char *mask_alpha_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" @@ -104,6 +109,7 @@ glamor_create_composite_fs(struct shader_key *key) " return texture2D(mask_sampler, mask_texture);\n" "}\n"; const char *mask_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" @@ -111,21 +117,25 @@ glamor_create_composite_fs(struct shader_key *key) " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" "}\n"; const char *in_source_only = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" " gl_FragColor = get_source();\n" "}\n"; const char *in_normal = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" " gl_FragColor = get_source() * get_mask().a;\n" "}\n"; const char *in_ca_source = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" " gl_FragColor = get_source() * get_mask();\n" "}\n"; const char *in_ca_alpha = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" " gl_FragColor = get_source().a * get_mask();\n" diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 8fe4b3891..c184dac26 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -50,6 +50,7 @@ glamor_init_tile_shader(ScreenPtr screen) " tile_texture = v_texcoord0.xy;\n" "}\n"; const char *tile_fs = + GLAMOR_DEFAULT_PRECISION "varying vec2 tile_texture;\n" "uniform sampler2D sampler;\n" "void main()\n" From 3854409e9ad25418c6188f491410bb05eaf92fc6 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 22 Aug 2011 23:27:24 -0700 Subject: [PATCH 199/462] glamor: Fix direct call for glEGLImageTargetTexture2DOES Follow extension call rule to call glEGLImageTargetTexture2DOES. --- hw/xfree86/glamor/glamor.c | 40 ++++----------------------------- hw/xfree86/glamor/glamor_crtc.c | 3 ++- hw/xfree86/glamor/glamor_ddx.h | 37 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 3ac003dc2..109477bad 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -35,19 +35,6 @@ #include #include -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#define EGL_DISPLAY_NO_X_MESA - -#if GLAMOR_GLES2 -#include -#else -#include -#endif - -#define MESA_EGL_NO_X11_HEADERS -#include -#include #include "../../../mi/micmap.h" #include @@ -70,27 +57,6 @@ glamor_identify(int flags) xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver\n", glamor_name); } -struct glamor_screen_private { - EGLDisplay display; - EGLContext context; - EGLImageKHR root; - EGLint major, minor; - - CreateScreenResourcesProcPtr CreateScreenResources; - CloseScreenProcPtr CloseScreen; - int fd; - int cpp; - - PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; - PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; - -}; - -static inline struct glamor_screen_private * -glamor_get_screen_private(ScrnInfoPtr scrn) -{ - return (struct glamor_screen_private *) (scrn->driverPrivate); -} Bool glamor_resize(ScrnInfoPtr scrn, int width, int height) @@ -122,7 +88,7 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); glamor_set_screen_pixmap_texture(screen, width, height, texture); glamor->root = image; @@ -394,8 +360,10 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) glamor->egl_create_drm_image_mesa = (PFNEGLCREATEDRMIMAGEMESA)eglGetProcAddress("eglCreateDRMImageMESA"); glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA)eglGetProcAddress("eglExportDRMImageMESA"); + glamor->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - if (!glamor->egl_create_drm_image_mesa || !glamor->egl_export_drm_image_mesa) { + if (!glamor->egl_create_drm_image_mesa || !glamor->egl_export_drm_image_mesa || + !glamor->egl_image_target_texture2d_oes) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetProcAddress() failed\n"); return FALSE; diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 959201397..ef6ee2946 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -478,6 +478,7 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ScrnInfoPtr scrn = crtc->scrn; + struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); if (drmmode_crtc->cursor == NULL) { @@ -490,7 +491,7 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, drmmode_crtc->cursor); + (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, drmmode_crtc->cursor); } glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); #ifdef GLAMOR_GLES2 diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index 0e164d3b7..6d9e410f0 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -1,6 +1,43 @@ #ifndef GLAMOR_DDX_H #define GLAMOR_DDX_H +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#define EGL_DISPLAY_NO_X_MESA + +#if GLAMOR_GLES2 +#include +#include +#else +#include +#endif + +#define MESA_EGL_NO_X11_HEADERS +#include +#include + +struct glamor_screen_private { + EGLDisplay display; + EGLContext context; + EGLImageKHR root; + EGLint major, minor; + + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + int fd; + int cpp; + + PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; + PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; +}; + +inline struct glamor_screen_private * +glamor_get_screen_private(ScrnInfoPtr scrn) +{ + return (struct glamor_screen_private *) (scrn->driverPrivate); +} + Bool glamor_resize(ScrnInfoPtr scrn, int width, int height); void glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch); From 60f14d60f6169272951d41d8ca9e0a294c2ca3d0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 24 Aug 2011 16:54:32 +0800 Subject: [PATCH 200/462] glamor-egl: Move EGL surfaceless related code to dix module. The functions in glamor_egl.c could be shared by any egl back end drivers. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 8 + glamor/glamor_egl.c | 296 +++++++++++++++++++++++++++++++++ hw/xfree86/dixmods/Makefile.am | 5 +- 3 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 glamor/glamor_egl.c diff --git a/glamor/glamor.h b/glamor/glamor.h index 25f4506d2..ef13b7a66 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -43,6 +43,14 @@ #define GLAMOR_HOSTX 2 #define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS | GLAMOR_HOSTX) +#define GLAMOR_EGL_EXTERNAL_BUFFER 3 + extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); + +extern _X_EXPORT Bool glamor_egl_init(ScreenPtr screen, int fd); +extern _X_EXPORT Bool glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride); +extern _X_EXPORT Bool glamor_close_egl_screen(ScreenPtr screen); +extern _X_EXPORT void glamor_free_egl_screen(int scrnIndex, int flags); + diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c new file mode 100644 index 000000000..a92993b7a --- /dev/null +++ b/glamor/glamor_egl.c @@ -0,0 +1,296 @@ +/* + * Copyright © 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including + * the next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#define EGL_DISPLAY_NO_X_MESA + +#if GLAMOR_GLES2 +#include +#else +#include +#endif + +#define MESA_EGL_NO_X11_HEADERS +#include +#include + +#include + +#define GLAMOR_VERSION_MAJOR 0 +#define GLAMOR_VERSION_MINOR 1 +#define GLAMOR_VERSION_PATCH 0 + +static const char glamor_name[] = "glamor"; + +static void +glamor_identify(int flags) +{ + xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver based.\n", glamor_name); +} + +struct glamor_screen_private { + EGLDisplay display; + EGLContext context; + EGLImageKHR root; + EGLint major, minor; + + + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + int fd; + int front_buffer_handle; + int cpp; + + PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; + PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; + PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; + +}; + +int xf86GlamorEGLPrivateIndex = -1; + +static struct glamor_screen_private* glamor_get_egl_screen_private(ScrnInfoPtr scrn) +{ + return (struct glamor_screen_private *) scrn->privates[xf86GlamorEGLPrivateIndex].ptr; +} + +static Bool +_glamor_create_egl_screen_image(ScrnInfoPtr scrn, int width, int height, int stride) +{ + + struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; + EGLImageKHR image; + GLuint texture; + EGLint attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_STRIDE_MESA, 0, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA | + EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_NONE + }; + + if (glamor->root) { + eglDestroyImageKHR(glamor->display, glamor->root); + glamor->root = EGL_NO_IMAGE_KHR; + } + + attribs[1] = width; + attribs[3] = height; + attribs[5] = stride / 4; + image = glamor->egl_create_image_khr (glamor->display, + glamor->context, + EGL_DRM_BUFFER_MESA, + (void*)glamor->front_buffer_handle, + attribs); + if (image == EGL_NO_IMAGE_KHR) + return FALSE; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + + glamor_set_screen_pixmap_texture(screen, width, height, texture); + glamor->root = image; + return TRUE; +} + +Bool +glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); + struct drm_gem_flink flink; + flink.handle = handle; + + if (ioctl(glamor->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink front buffer handle\n"); + return FALSE; + } + + glamor->front_buffer_handle = flink.name; + + return _glamor_create_egl_screen_image(scrn, scrn->virtualX, scrn->virtualY, stride); +} + +Bool +glamor_close_egl_screen(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); + glamor_fini(screen); + + eglDestroyImageKHR(glamor->display, glamor->root); + + + glamor->root = EGL_NO_IMAGE_KHR; + + return TRUE; +} + + + +static Bool +glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) +{ + const char *egl_extensions; + char *pext; + int ext_len; + ext_len = strlen(extension); + + egl_extensions = (const char*)eglQueryString(glamor->display, EGL_EXTENSIONS); + pext = (char*)egl_extensions; + + if (pext == NULL || extension == NULL) + return FALSE; + while((pext = strstr(pext, extension)) != NULL) { + if (pext[ext_len] == ' ' || pext[ext_len] == '\0') + return TRUE; + pext += ext_len; + } + return FALSE; +} + + +Bool glamor_egl_init(ScreenPtr screen, int fd) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor; + const char *version; + EGLint config_attribs[] = { +#ifdef GLAMOR_GLES2 + EGL_CONTEXT_CLIENT_VERSION, 2, +#endif + EGL_NONE + }; + + glamor_identify(0); + glamor = calloc(sizeof(*glamor), 1); + if (xf86GlamorEGLPrivateIndex == -1) + xf86GlamorEGLPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + + scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor; + + glamor->fd = fd; + glamor->display = eglGetDRMDisplayMESA(glamor->fd); +#ifndef GLAMOR_GLES2 + eglBindAPI(EGL_OPENGL_API); +#else + eglBindAPI(EGL_OPENGL_ES_API); +#endif + if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "eglInitialize() failed\n"); + return FALSE; + } + + version = eglQueryString(glamor->display, EGL_VERSION); + xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); + +#define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ + if (!glamor_egl_has_extension(glamor, "EGL_" #EXT)) { \ + ErrorF("EGL_" #EXT "required.\n"); \ + return FALSE; \ + } + + GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); + GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); +#ifdef GLAMOR_GLES2 + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_gles2); +#else + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); +#endif + + glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA) + eglGetProcAddress("eglExportDRMImageMESA"); + glamor->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) + eglGetProcAddress("eglCreateImageKHR"); + + if (!glamor->egl_create_image_khr + || !glamor->egl_export_drm_image_mesa) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "eglGetProcAddress() failed\n"); + return FALSE; + } + + glamor->context = eglCreateContext(glamor->display, + NULL, EGL_NO_CONTEXT, config_attribs); + if (glamor->context == EGL_NO_CONTEXT) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to create EGL context\n"); + return FALSE; + } + + if (!eglMakeCurrent(glamor->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, glamor->context)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make EGL context current\n"); + return FALSE; + } + + if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to initialize glamor\n"); + return FALSE; + } + return TRUE; +} + +void +glamor_free_egl_screen(int scrnIndex, int flags) +{ + ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); + + if (glamor != NULL) + { + if (!(flags & GLAMOR_EGL_EXTERNAL_BUFFER)) { + eglMakeCurrent(glamor->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + eglTerminate(glamor->display); + } + free(glamor); + } +} diff --git a/hw/xfree86/dixmods/Makefile.am b/hw/xfree86/dixmods/Makefile.am index 84c909b9c..ba4aeb402 100644 --- a/hw/xfree86/dixmods/Makefile.am +++ b/hw/xfree86/dixmods/Makefile.am @@ -34,6 +34,7 @@ INCLUDES = @XORG_INCS@ \ -I$(top_srcdir)/hw/xfree86/loader \ -I$(top_srcdir)/miext/shadow \ -I$(top_srcdir)/glx + libdbe_la_LDFLAGS = -avoid-version libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la @@ -41,8 +42,8 @@ libdbe_la_SOURCES = dbemodule.c if GLAMOR libglamor_dix_la_LDFLAGS = -avoid-version libglamor_dix_la_LIBADD = $(top_builddir)/glamor/libglamor.la -libglamor_dix_la_SOURCES = glamor_module.c -libglamor_dix_la_CFLAGS = $(AM_CFLAGS) +libglamor_dix_la_SOURCES = glamor_module.c $(top_srcdir)/glamor/glamor_egl.c +libglamor_dix_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/glamor $(LIBDRM_CFLAGS) endif libfb_la_LDFLAGS = -avoid-version libfb_la_LIBADD = $(top_builddir)/fb/libfb.la From 6cb4abca697c24bdc644502cce8a2ca9bbf131e3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 24 Aug 2011 17:13:35 +0800 Subject: [PATCH 201/462] glamor: Remove the version check for EGL/gles. As PVR's gles2 has different version number from mesa's, just simply remove the version check here to let both platform could build it. Signed-off-by: Zhigang Gong --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 2a1c7869d..82c845ba7 100644 --- a/configure.ac +++ b/configure.ac @@ -801,8 +801,8 @@ LIBUDEV="libudev >= 143" LIBSELINUX="libselinux >= 2.0.86" LIBDBUS="dbus-1 >= 1.0" LIBPIXMAN="pixman-1 >= 0.21.8" -LIBEGL="egl >= 7.11.0" -LIBGLESV2="glesv2 >= 7.11.0" +LIBEGL="egl" +LIBGLESV2="glesv2" dnl Pixman is always required, but we separate it out so we can link dnl specific modules against it PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) From d4f4d1272e1745752840eb7e8ec04eb155ac38d1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 24 Aug 2011 17:17:48 +0800 Subject: [PATCH 202/462] glamor-egl: Fix direct call for glEGLImageTargetTexture2DOES. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index a92993b7a..7848c51ef 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -42,6 +42,7 @@ #if GLAMOR_GLES2 #include +#include #else #include #endif @@ -80,7 +81,7 @@ struct glamor_screen_private { PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; - + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; }; int xf86GlamorEGLPrivateIndex = -1; @@ -128,7 +129,8 @@ _glamor_create_egl_screen_image(ScrnInfoPtr scrn, int width, int height, int str glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + + (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); glamor_set_screen_pixmap_texture(screen, width, height, texture); glamor->root = image; @@ -247,8 +249,12 @@ Bool glamor_egl_init(ScreenPtr screen, int fd) glamor->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); + glamor->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) + eglGetProcAddress("glEGLImageTargetTexture2DOES"); + if (!glamor->egl_create_image_khr - || !glamor->egl_export_drm_image_mesa) { + || !glamor->egl_export_drm_image_mesa + || !glamor->egl_image_target_texture2d_oes) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetProcAddress() failed\n"); return FALSE; From ae38bd7c459982d3e05f6f672ee68d187e97421c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 25 Aug 2011 10:05:11 +0800 Subject: [PATCH 203/462] glamor: Change glamor_egl_init API. Slightly change the API glamor_egl_init, as this initialization is to initialize the display not the screen, we should call it in xxx_preinit rather than xxxScreenInit(). we change the input parameter as below, as in preInit, the screen may not be allocated at all. And in glamor_egl_init, it will not call glamor_init. Driver should call glamor_init at screen_init stage. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 3 ++- glamor/glamor_egl.c | 8 +------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index ef13b7a66..3c74c723e 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -29,6 +29,7 @@ #define GLAMOR_H #include "scrnintstr.h" +#include "xf86str.h" #include "pixmapstr.h" #include "windowstr.h" #include "gcstruct.h" @@ -49,7 +50,7 @@ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); -extern _X_EXPORT Bool glamor_egl_init(ScreenPtr screen, int fd); +extern _X_EXPORT Bool glamor_egl_init(ScrnInfoPtr scrn, int fd); extern _X_EXPORT Bool glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride); extern _X_EXPORT Bool glamor_close_egl_screen(ScreenPtr screen); extern _X_EXPORT void glamor_free_egl_screen(int scrnIndex, int flags); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 7848c51ef..293e8dea9 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -195,9 +195,8 @@ glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) } -Bool glamor_egl_init(ScreenPtr screen, int fd) +Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_screen_private *glamor; const char *version; EGLint config_attribs[] = { @@ -275,11 +274,6 @@ Bool glamor_egl_init(ScreenPtr screen, int fd) return FALSE; } - if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to initialize glamor\n"); - return FALSE; - } return TRUE; } From bf4cbbd4e9c8ee104293a3c4eb202c880a139b73 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 30 Aug 2011 17:37:47 +0800 Subject: [PATCH 204/462] glamor: Move glamor_glyphs_init to create screen resources stage. As in glamor_glyphs_init, we may need to create pixmap. Thus it must be called after the pixmap resources allocation. Just move it to screen resource creation stage is good enough for mow. Also introduce a macro GLAMOR_FOR_XORG to glamor.h. As glamor may be used by Xephyr which doesn't don't have those xorg header files and also don't need the egl extension. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 - glamor/glamor.h | 6 +++++- glamor/glamor_egl.c | 2 ++ hw/kdrive/ephyr/ephyr.c | 8 ++++++-- hw/xfree86/glamor/glamor.c | 3 ++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index cd261ac8b..53fe71d49 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -364,7 +364,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_tile_shader(screen); glamor_init_putimage_shaders(screen); glamor_init_finish_access_shaders(screen); - glamor_glyphs_init(screen); glamor_pixmap_init(screen); #ifdef GLAMOR_GLES2 diff --git a/glamor/glamor.h b/glamor/glamor.h index 3c74c723e..7a0e89923 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -29,7 +29,9 @@ #define GLAMOR_H #include "scrnintstr.h" +#ifdef GLAMOR_FOR_XORG #include "xf86str.h" +#endif #include "pixmapstr.h" #include "windowstr.h" #include "gcstruct.h" @@ -49,9 +51,11 @@ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); +extern _X_EXPORT Bool glamor_glyphs_init (ScreenPtr pScreen); +#ifdef GLAMOR_FOR_XORG extern _X_EXPORT Bool glamor_egl_init(ScrnInfoPtr scrn, int fd); extern _X_EXPORT Bool glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride); extern _X_EXPORT Bool glamor_close_egl_screen(ScreenPtr screen); extern _X_EXPORT void glamor_free_egl_screen(int scrnIndex, int flags); - +#endif diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 293e8dea9..bdb2da711 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -51,6 +51,8 @@ #include #include +#define GLAMOR_FOR_XORG + #include #define GLAMOR_VERSION_MAJOR 0 diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 4bead1f36..e2cd7a49d 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -684,6 +684,7 @@ ephyrInitScreen (ScreenPtr pScreen) return TRUE; } + Bool ephyrFinishInitScreen (ScreenPtr pScreen) { @@ -700,6 +701,7 @@ ephyrFinishInitScreen (ScreenPtr pScreen) return TRUE; } +extern Bool ephyr_glamor; Bool ephyrCreateResources (ScreenPtr pScreen) @@ -710,14 +712,16 @@ ephyrCreateResources (ScreenPtr pScreen) EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", pScreen, pScreen->myNum, scrpriv->shadow); - if (scrpriv->shadow) return KdShadowSet (pScreen, scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear); - else + else { + if (ephyr_glamor) + if (!glamor_glyphs_init(pScreen)) return FALSE; return ephyrSetInternalDamage(pScreen); + } } void diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 109477bad..9c9be894f 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -233,7 +233,8 @@ glamor_create_screen_resources_ddx(ScreenPtr screen) screen->CreateScreenResources = glamor->CreateScreenResources; if (!(*screen->CreateScreenResources) (screen)) return FALSE; - + if (!glamor_glyphs_init(screen)) + return FALSE; if (!xf86SetDesiredModes(scrn)) return FALSE; From 16659622708db82caaeb12527ba09545ad15b4c3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 30 Aug 2011 17:45:07 +0800 Subject: [PATCH 205/462] glamor: Improve glyphs cache mechanism. This commit applying the latest uxa's glyphs cache mechanism and give up the old hash based cache algorithm. And the cache picture now is much larger than the previous one also. This new algorithm can avoid the hash insert/remove and also the expensive sha1 checking. It could obtain about 10% performance gain when rendering glyphs. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 1419 ++++++++++++++++++++-------------------- glamor/glamor_priv.h | 43 +- glamor/glamor_render.c | 8 +- 3 files changed, 714 insertions(+), 756 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 63ffd205c..af6ec71a1 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -60,13 +60,16 @@ * max texture size of the driver; this may need to actually come from * the driver. */ -#define CACHE_PICTURE_WIDTH 1024 /* Maximum number of glyphs we buffer on the stack before flushing * rendering to the mask or destination surface. */ -#define GLYPH_BUFFER_SIZE 256 +#define GLYPH_BUFFER_SIZE 1024 +#define CACHE_PICTURE_SIZE 1024 +#define GLYPH_MIN_SIZE 8 +#define GLYPH_MAX_SIZE 64 +#define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) typedef struct { PicturePtr source; @@ -74,76 +77,64 @@ typedef struct { int count; } glamor_glyph_buffer_t; +struct glamor_glyph +{ + glamor_glyph_cache_t *cache; + uint16_t x, y; + uint16_t size, pos; +}; + typedef enum { GLAMOR_GLYPH_SUCCESS, /* Glyph added to render buffer */ GLAMOR_GLYPH_FAIL, /* out of memory, etc */ GLAMOR_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ } glamor_glyph_cache_result_t; -void glamor_glyphs_init(ScreenPtr screen) -{ - glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); - int i = 0; - memset(glamor_screen->glyph_caches, 0, sizeof(glamor_screen->glyph_caches)); - - glamor_screen->glyph_caches[i].format = PICT_a8; - glamor_screen->glyph_caches[i].glyph_width = - glamor_screen->glyph_caches[i].glyph_height = 16; - i++; - glamor_screen->glyph_caches[i].format = PICT_a8; - glamor_screen->glyph_caches[i].glyph_width = - glamor_screen->glyph_caches[i].glyph_height = 32; - i++; - glamor_screen->glyph_caches[i].format = PICT_a8r8g8b8; - glamor_screen->glyph_caches[i].glyph_width = - glamor_screen->glyph_caches[i].glyph_height = 16; - i++; - glamor_screen->glyph_caches[i].format = PICT_a8r8g8b8; - glamor_screen->glyph_caches[i].glyph_width = - glamor_screen->glyph_caches[i].glyph_height = 32; - i++; - - assert(i == GLAMOR_NUM_GLYPH_CACHES); - - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { - glamor_screen->glyph_caches[i].columns = - CACHE_PICTURE_WIDTH / glamor_screen->glyph_caches[i].glyph_width; - glamor_screen->glyph_caches[i].size = 256; - glamor_screen->glyph_caches[i].hash_size = 557; - } -} - -static void glamor_unrealize_glyph_caches(ScreenPtr screen, unsigned int format) -{ - glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); - int i; - - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { - glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; - - if (cache->format != format) - continue; - - if (cache->picture) { - FreePicture((pointer) cache->picture, (XID) 0); - cache->picture = NULL; - } - - if (cache->hash_entries) { - free(cache->hash_entries); - cache->hash_entries = NULL; - } - - if (cache->glyphs) { - free(cache->glyphs); - cache->glyphs = NULL; - } - cache->glyph_count = 0; - } -} #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) +static DevPrivateKeyRec glamor_glyph_key; + +static inline struct glamor_glyph * +glamor_glyph_get_private (GlyphPtr glyph) +{ + return dixGetPrivate (&glyph->devPrivates, &glamor_glyph_key); +} + +static inline void +glamor_glyph_set_private (GlyphPtr glyph, struct glamor_glyph *priv) +{ + dixSetPrivate (&glyph->devPrivates, &glamor_glyph_key, priv); +} + + +static void +glamor_unrealize_glyph_caches (ScreenPtr pScreen) +{ + glamor_screen_private *glamor = glamor_get_screen_private (pScreen); + int i; + + if (!glamor->glyph_cache_initialized) + return; + + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHE_FORMATS; i++) + { + glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; + + if (cache->picture) + FreePicture (cache->picture, 0); + + if (cache->glyphs) + free (cache->glyphs); + } + glamor->glyph_cache_initialized = FALSE; +} + +void +glamor_glyphs_fini (ScreenPtr pScreen) +{ + glamor_unrealize_glyph_caches (pScreen); +} /* All caches for a single format share a single pixmap for glyph storage, * allowing mixing glyphs of different sizes without paying a penalty @@ -154,512 +145,221 @@ static void glamor_unrealize_glyph_caches(ScreenPtr screen, unsigned int format) * This function allocates the storage pixmap, and then fills in the * rest of the allocated structures for all caches with the given format. */ -static Bool glamor_realize_glyph_caches(ScreenPtr screen, unsigned int format) +static Bool +glamor_realize_glyph_caches (ScreenPtr pScreen) { - glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); - int depth = PIXMAN_FORMAT_DEPTH(format); - PictFormatPtr pict_format; - PixmapPtr pixmap; - PicturePtr picture; - CARD32 component_alpha; - int height; - int i; - int error; + glamor_screen_private *glamor = glamor_get_screen_private (pScreen); + unsigned int formats[] = { + PIXMAN_a8, + PIXMAN_a8r8g8b8, + }; + int i; - pict_format = PictureMatchFormat(screen, depth, format); - if (!pict_format) - return FALSE; - - /* Compute the total vertical size needed for the format */ - - height = 0; - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { - glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; - int rows; - - if (cache->format != format) - continue; - - cache->y_offset = height; - - rows = (cache->size + cache->columns - 1) / cache->columns; - height += rows * cache->glyph_height; - } - - /* Now allocate the pixmap and picture */ - - pixmap = screen->CreatePixmap(screen, - CACHE_PICTURE_WIDTH, - height, depth, - 0); - if (!pixmap) - return FALSE; - - component_alpha = NeedsComponent(pict_format->format); - picture = CreatePicture(0, &pixmap->drawable, pict_format, - CPComponentAlpha, &component_alpha, - serverClient, &error); - - screen->DestroyPixmap(pixmap); /* picture holds a refcount */ - - if (!picture) - return FALSE; - - /* And store the picture in all the caches for the format */ - - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { - glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; - int j; - - if (cache->format != format) - continue; - - cache->picture = picture; - cache->picture->refcnt++; - cache->hash_entries = malloc(sizeof(int) * cache->hash_size); - cache->glyphs = - malloc(sizeof(glamor_cached_glyph_t) * cache->size); - cache->glyph_count = 0; - - if (!cache->hash_entries || !cache->glyphs) - goto bail; - - for (j = 0; j < cache->hash_size; j++) - cache->hash_entries[j] = -1; - - cache->eviction_position = rand() % cache->size; - } - - /* Each cache references the picture individually */ - FreePicture(picture, 0); + if (glamor->glyph_cache_initialized) return TRUE; - bail: - glamor_unrealize_glyph_caches(screen, format); + glamor->glyph_cache_initialized = TRUE; + memset (glamor->glyphCaches, 0, sizeof (glamor->glyphCaches)); + + for (i = 0; i < sizeof (formats) / sizeof (formats[0]); i++) + { + glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; + PixmapPtr pixmap; + PicturePtr picture; + CARD32 component_alpha; + int depth = PIXMAN_FORMAT_DEPTH (formats[i]); + int error; + PictFormatPtr pPictFormat = + PictureMatchFormat (pScreen, depth, formats[i]); + if (!pPictFormat) + goto bail; + + /* Now allocate the pixmap and picture */ + pixmap = pScreen->CreatePixmap (pScreen, + CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, + depth, 0); + if (!pixmap) + goto bail; + + component_alpha = NeedsComponent (pPictFormat->format); + picture = CreatePicture (0, &pixmap->drawable, pPictFormat, + CPComponentAlpha, &component_alpha, + serverClient, &error); + + pScreen->DestroyPixmap (pixmap); + if (!picture) + goto bail; + + ValidatePicture (picture); + + cache->picture = picture; + cache->glyphs = calloc (sizeof (GlyphPtr), GLYPH_CACHE_SIZE); + if (!cache->glyphs) + goto bail; + + cache->evict = rand () % GLYPH_CACHE_SIZE; + } + assert (i == GLAMOR_NUM_GLYPH_CACHE_FORMATS); + + return TRUE; + +bail: + glamor_unrealize_glyph_caches (pScreen); + return FALSE; +} + + +Bool +glamor_glyphs_init (ScreenPtr pScreen) +{ + if (!dixRegisterPrivateKey (&glamor_glyph_key, PRIVATE_GLYPH, 0)) return FALSE; + + /* Skip pixmap creation if we don't intend to use it. */ + + return glamor_realize_glyph_caches (pScreen); } -void glamor_glyphs_fini(ScreenPtr screen) -{ - glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); - int i; - - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { - glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; - - if (cache->picture) - glamor_unrealize_glyph_caches(screen, cache->format); - } -} - -static int -glamor_glyph_cache_hash_lookup(glamor_glyph_cache_t * cache, GlyphPtr glyph) -{ - int slot; - - slot = (*(CARD32 *) glyph->sha1) % cache->hash_size; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hash_entries[slot]; - if (entryPos == -1) - return -1; - - if (memcmp(glyph->sha1, cache->glyphs[entryPos].sha1, - sizeof(glyph->sha1)) == 0) { - return entryPos; - } - - slot--; - if (slot < 0) - slot = cache->hash_size - 1; - } -} - -static void -glamor_glyph_cache_hash_insert(glamor_glyph_cache_t * cache, GlyphPtr glyph, int pos) -{ - int slot; - - memcpy(cache->glyphs[pos].sha1, glyph->sha1, sizeof(glyph->sha1)); - - slot = (*(CARD32 *) glyph->sha1) % cache->hash_size; - - while (TRUE) { /* hash table can never be full */ - if (cache->hash_entries[slot] == -1) { - cache->hash_entries[slot] = pos; - return; - } - - slot--; - if (slot < 0) - slot = cache->hash_size - 1; - } -} - -static void glamor_glyph_cache_hash_remove(glamor_glyph_cache_t * cache, int pos) -{ - int slot; - int emptied_slot = -1; - - slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hash_size; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hash_entries[slot]; - - if (entryPos == -1) - return; - - if (entryPos == pos) { - cache->hash_entries[slot] = -1; - emptied_slot = slot; - } else if (emptied_slot != -1) { - /* See if we can move this entry into the emptied slot, - * we can't do that if if entry would have hashed - * between the current position and the emptied slot. - * (taking wrapping into account). Bad positions - * are: - * - * | XXXXXXXXXX | - * i j - * - * |XXX XXXX| - * j i - * - * i - slot, j - emptied_slot - * - * (Knuth 6.4R) - */ - - int entry_slot = (*(CARD32 *) cache->glyphs[entryPos].sha1) % - cache->hash_size; - - if (!((entry_slot >= slot && entry_slot < emptied_slot) || - (emptied_slot < slot - && (entry_slot < emptied_slot - || entry_slot >= slot)))) { - cache->hash_entries[emptied_slot] = entryPos; - cache->hash_entries[slot] = -1; - emptied_slot = slot; - } - } - - slot--; - if (slot < 0) - slot = cache->hash_size - 1; - } -} - -#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyph_width) -#define CACHE_Y(pos) (cache->y_offset + ((pos) / cache->columns) * cache->glyph_height) - /* The most efficient thing to way to upload the glyph to the screen * is to use CopyArea; glamor pixmaps are always offscreen. */ -static Bool -glamor_glyph_cache_upload_glyph(ScreenPtr screen, - glamor_glyph_cache_t * cache, - int pos, GlyphPtr glyph) +static void +glamor_glyph_cache_upload_glyph (ScreenPtr screen, + glamor_glyph_cache_t * cache, + GlyphPtr glyph, int x, int y) { - PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; - PixmapPtr glyph_pixmap = (PixmapPtr) glyph_picture->pDrawable; - PixmapPtr cache_pixmap = (PixmapPtr) cache->picture->pDrawable; - PixmapPtr scratch; - GCPtr gc; + PicturePtr pGlyphPicture = GlyphPicture (glyph)[screen->myNum]; + PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; + PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; + PixmapPtr scratch; + GCPtr gc; - /* UploadToScreen only works if bpp match */ - if (glyph_pixmap->drawable.bitsPerPixel != - cache_pixmap->drawable.bitsPerPixel) - return FALSE; + gc = GetScratchGC (pCachePixmap->drawable.depth, screen); + if (!gc) + return; - gc = GetScratchGC(cache_pixmap->drawable.depth, screen); - ValidateGC(&cache_pixmap->drawable, gc); + ValidateGC (&pCachePixmap->drawable, gc); - /* Create a temporary bo to stream the updates to the cache */ + scratch = pGlyphPixmap; #if 0 - scratch = screen->CreatePixmap(screen, - glyph->info.width, - glyph->info.height, - glyph_pixmap->drawable.depth, - 0); - if (scratch) { - (void)glamor_copy_area(&glyph_pixmap->drawable, - &scratch->drawable, - gc, - 0, 0, - glyph->info.width, glyph->info.height, - 0, 0); - } else { - scratch = glyph_pixmap; - } -#endif - scratch = glyph_pixmap; - (void)glamor_copy_area(&scratch->drawable, - &cache_pixmap->drawable, - gc, - 0, 0, glyph->info.width, glyph->info.height, - CACHE_X(pos), CACHE_Y(pos)); + /* Create a temporary bo to stream the updates to the cache */ + if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth || + !uxa_pixmap_is_offscreen (scratch)) + { + scratch = screen->CreatePixmap (screen, + glyph->info.width, + glyph->info.height, + pCachePixmap->drawable.depth, 0); + if (scratch) + { + if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) + { + PicturePtr picture; + int error; - if (scratch != glyph_pixmap) - screen->DestroyPixmap(scratch); - - FreeScratchGC(gc); - - return TRUE; -} - -static glamor_glyph_cache_result_t -glamor_glyph_cache_buffer_glyph(ScreenPtr screen, - glamor_glyph_cache_t * cache, - glamor_glyph_buffer_t * buffer, - GlyphPtr glyph, int x_glyph, int y_glyph) -{ - glamor_composite_rect_t *rect; - int pos; - - if (buffer->source && buffer->source != cache->picture) - return GLAMOR_GLYPH_NEED_FLUSH; - - if (!cache->picture) { - if (!glamor_realize_glyph_caches(screen, cache->format)) - return GLAMOR_GLYPH_FAIL; - } - - DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n", - cache->glyph_width, cache->glyph_height, - cache->format == PICT_a8 ? "A" : "ARGB", - (long)*(CARD32 *) glyph->sha1)); - - pos = glamor_glyph_cache_hash_lookup(cache, glyph); - if (pos != -1) { - DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos)); - } else { - if (cache->glyph_count < cache->size) { - /* Space remaining; we fill from the start */ - pos = cache->glyph_count; - cache->glyph_count++; - DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos)); - - glamor_glyph_cache_hash_insert(cache, glyph, pos); - - } else { - /* Need to evict an entry. We have to see if any glyphs - * already in the output buffer were at this position in - * the cache - */ - - pos = cache->eviction_position; - DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); - if (buffer->count) { - int x, y; - int i; - - x = CACHE_X(pos); - y = CACHE_Y(pos); - - for (i = 0; i < buffer->count; i++) { - if (buffer->rects[i].x_src == x - && buffer->rects[i].y_src == y) { - DBG_GLYPH_CACHE((" must flush buffer\n")); - return GLAMOR_GLYPH_NEED_FLUSH; - } + picture = CreatePicture (0, &scratch->drawable, + PictureMatchFormat (screen, + pCachePixmap-> + drawable.depth, + cache->picture-> + format), 0, NULL, + serverClient, &error); + if (picture) + { + ValidatePicture (picture); + uxa_composite (PictOpSrc, pGlyphPicture, NULL, picture, + 0, 0, + 0, 0, + 0, 0, glyph->info.width, glyph->info.height); + FreePicture (picture, 0); } } - - /* OK, we're all set, swap in the new glyph */ - glamor_glyph_cache_hash_remove(cache, pos); - glamor_glyph_cache_hash_insert(cache, glyph, pos); - - /* And pick a new eviction position */ - cache->eviction_position = rand() % cache->size; - } - - /* Now actually upload the glyph into the cache picture; if - * we can't do it with UploadToScreen (because the glyph is - * offscreen, etc), we fall back to CompositePicture. - */ - if (!glamor_glyph_cache_upload_glyph(screen, cache, pos, glyph)) { - CompositePicture(PictOpSrc, - GlyphPicture(glyph)[screen->myNum], - None, - cache->picture, - 0, 0, - 0, 0, - CACHE_X(pos), - CACHE_Y(pos), - glyph->info.width, - glyph->info.height); - } - - } - - buffer->source = cache->picture; - - rect = &buffer->rects[buffer->count]; - rect->x_src = CACHE_X(pos); - rect->y_src = CACHE_Y(pos); - rect->x_dst = x_glyph - glyph->info.x; - rect->y_dst = y_glyph - glyph->info.y; - rect->width = glyph->info.width; - rect->height = glyph->info.height; - - buffer->count++; - - return GLAMOR_GLYPH_SUCCESS; -} - -#undef CACHE_X -#undef CACHE_Y - -static glamor_glyph_cache_result_t -glamor_buffer_glyph(ScreenPtr screen, - glamor_glyph_buffer_t *buffer, - GlyphPtr glyph, int x_glyph, int y_glyph) -{ - glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); - unsigned int format = (GlyphPicture(glyph)[screen->myNum])->format; - int width = glyph->info.width; - int height = glyph->info.height; - glamor_composite_rect_t *rect; - PicturePtr source; - int i; - - if (buffer->count == GLYPH_BUFFER_SIZE) - return GLAMOR_GLYPH_NEED_FLUSH; - - if (PICT_FORMAT_BPP(format) == 1) - format = PICT_a8; - - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHES; i++) { - glamor_glyph_cache_t *cache = &glamor_screen->glyph_caches[i]; - - if (format == cache->format && - width <= cache->glyph_width && - height <= cache->glyph_height) { - glamor_glyph_cache_result_t result = - glamor_glyph_cache_buffer_glyph(screen, - &glamor_screen->glyph_caches[i], - buffer, - glyph, x_glyph, - y_glyph); - switch (result) { - case GLAMOR_GLYPH_FAIL: - break; - case GLAMOR_GLYPH_SUCCESS: - case GLAMOR_GLYPH_NEED_FLUSH: - return result; + else + { + glamor_copy_area (&pGlyphPixmap->drawable, + &scratch->drawable, + gc, + 0, 0, + glyph->info.width, glyph->info.height, 0, 0); } } + else + { + scratch = pGlyphPixmap; + } } - - /* Couldn't find the glyph in the cache, use the glyph picture directly */ - - source = GlyphPicture(glyph)[screen->myNum]; - if (buffer->source && buffer->source != source) - return GLAMOR_GLYPH_NEED_FLUSH; - - buffer->source = source; - - rect = &buffer->rects[buffer->count]; - rect->x_src = 0; - rect->y_src = 0; - rect->x_dst = x_glyph - glyph->info.x; - rect->y_dst = y_glyph - glyph->info.y; - rect->width = glyph->info.width; - rect->height = glyph->info.height; - - buffer->count++; - - return GLAMOR_GLYPH_SUCCESS; -} - -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 + glamor_copy_area (&scratch->drawable, &pCachePixmap->drawable, gc, + 0, 0, glyph->info.width, glyph->info.height, x, y); - buffer->count = 0; - buffer->source = NULL; + if (scratch != pGlyphPixmap) + screen->DestroyPixmap (scratch); + + FreeScratchGC (gc); } -static void -glamor_glyphs_to_dst(CARD8 op, - PicturePtr src, - PicturePtr dst, - glamor_glyph_buffer_t *buffer, - INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst) + +void +glamor_glyph_unrealize (ScreenPtr screen, GlyphPtr glyph) { - int i; + struct glamor_glyph *priv; - for (i = 0; i < buffer->count; i++) { - glamor_composite_rect_t *rect = &buffer->rects[i]; + /* Use Lookup in case we have not attached to this glyph. */ + priv = dixLookupPrivate (&glyph->devPrivates, &glamor_glyph_key); + if (priv == NULL) + return; - CompositePicture(op, - src, - buffer->source, - dst, - x_src + rect->x_dst - x_dst, - y_src + rect->y_dst - y_dst, - rect->x_src, - rect->y_src, - rect->x_dst, - rect->y_dst, rect->width, rect->height); - } + priv->cache->glyphs[priv->pos] = NULL; - buffer->count = 0; - buffer->source = NULL; + glamor_glyph_set_private (glyph, NULL); + free (priv); } /* Cut and paste from render/glyph.c - probably should export it instead */ static void -glamor_glyph_extents(int nlist, - GlyphListPtr list, GlyphPtr *glyphs, BoxPtr extents) +glamor_glyph_extents (int nlist, + GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) { - int x1, x2, y1, y2; - int n; - GlyphPtr glyph; - int x, y; + int x1, x2, y1, y2; + int x, y, n; - x = 0; - y = 0; - extents->x1 = MAXSHORT; - extents->x2 = MINSHORT; - extents->y1 = MAXSHORT; - extents->y2 = MINSHORT; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) { - glyph = *glyphs++; - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; - if (x1 < extents->x1) - extents->x1 = x1; - if (x2 > extents->x2) - extents->x2 = x2; - if (y1 < extents->y1) - extents->y1 = y1; - if (y2 > extents->y2) - extents->y2 = y2; - x += glyph->info.xOff; - y += glyph->info.yOff; + x1 = y1 = MAXSHORT; + x2 = y2 = MINSHORT; + x = y = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + GlyphPtr glyph = *glyphs++; + int v; + + v = x - glyph->info.x; + if (v < x1) + x1 = v; + v += glyph->info.width; + if (v > x2) + x2 = v; + + v = y - glyph->info.y; + if (v < y1) + y1 = v; + v += glyph->info.height; + if (v > y2) + y2 = v; + + x += glyph->info.xOff; + y += glyph->info.yOff; } } + + extents->x1 = x1 < MINSHORT ? MINSHORT : x1; + extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2; + extents->y1 = y1 < MINSHORT ? MINSHORT : y1; + extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2; } /** @@ -667,217 +367,494 @@ glamor_glyph_extents(int nlist, * bounding box, which appears to be good enough to catch most cases at least. */ static Bool -glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) +glamor_glyphs_intersect (int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - int x1, x2, y1, y2; - int n; - GlyphPtr glyph; - int x, y; - BoxRec extents; - Bool first = TRUE; + int x1, x2, y1, y2; + int n; + int x, y; + BoxRec extents; + Bool first = TRUE; - x = 0; - y = 0; - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = 0; - extents.y2 = 0; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) { - glyph = *glyphs++; + x = 0; + y = 0; + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = 0; + extents.y2 = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + GlyphPtr glyph = *glyphs++; - if (glyph->info.width == 0 || glyph->info.height == 0) { - x += glyph->info.xOff; - y += glyph->info.yOff; - continue; + if (glyph->info.width == 0 || glyph->info.height == 0) + { + x += glyph->info.xOff; + y += glyph->info.yOff; + continue; } - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; - if (first) { - extents.x1 = x1; - extents.y1 = y1; - extents.x2 = x2; - extents.y2 = y2; - first = FALSE; - } else { - if (x1 < extents.x2 && x2 > extents.x1 && - y1 < extents.y2 && y2 > extents.y1) { - return TRUE; + if (first) + { + extents.x1 = x1; + extents.y1 = y1; + extents.x2 = x2; + extents.y2 = y2; + first = FALSE; + } + else + { + if (x1 < extents.x2 && x2 > extents.x1 && + y1 < extents.y2 && y2 > extents.y1) + { + return TRUE; } - if (x1 < extents.x1) - extents.x1 = x1; - if (x2 > extents.x2) - extents.x2 = x2; - if (y1 < extents.y1) - extents.y1 = y1; - if (y2 > extents.y2) - extents.y2 = y2; + if (x1 < extents.x1) + extents.x1 = x1; + if (x2 > extents.x2) + extents.x2 = x2; + if (y1 < extents.y1) + extents.y1 = y1; + if (y2 > extents.y2) + extents.y2 = y2; } - x += glyph->info.xOff; - y += glyph->info.yOff; + x += glyph->info.xOff; + y += glyph->info.yOff; } } - return FALSE; + return FALSE; +} + + +static inline unsigned int +glamor_glyph_size_to_count (int size) +{ + size /= GLYPH_MIN_SIZE; + return size * size; +} + +static inline unsigned int +glamor_glyph_count_to_mask (int count) +{ + return ~(count - 1); +} + +static inline unsigned int +glamor_glyph_size_to_mask (int size) +{ + return glamor_glyph_count_to_mask (glamor_glyph_size_to_count (size)); +} + +static PicturePtr +glamor_glyph_cache (ScreenPtr screen, GlyphPtr glyph, int *out_x, int *out_y) +{ + glamor_screen_private *glamor = glamor_get_screen_private (screen); + PicturePtr glyph_picture = GlyphPicture (glyph)[screen->myNum]; + glamor_glyph_cache_t *cache = + &glamor->glyphCaches[PICT_FORMAT_RGB (glyph_picture->format) != 0]; + struct glamor_glyph *priv = NULL; + int size, mask, pos, s; + + if (glyph->info.width > GLYPH_MAX_SIZE + || glyph->info.height > GLYPH_MAX_SIZE) + return NULL; + + for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2) + if (glyph->info.width <= size && glyph->info.height <= size) + break; + + s = glamor_glyph_size_to_count (size); + mask = glamor_glyph_count_to_mask (s); + pos = (cache->count + s - 1) & mask; + if (pos < GLYPH_CACHE_SIZE) + { + cache->count = pos + s; + } + else + { + for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) + { + int i = cache->evict & glamor_glyph_size_to_mask (s); + GlyphPtr evicted = cache->glyphs[i]; + if (evicted == NULL) + continue; + + priv = glamor_glyph_get_private (evicted); + if (priv->size >= s) + { + cache->glyphs[i] = NULL; + glamor_glyph_set_private (evicted, NULL); + pos = cache->evict & glamor_glyph_size_to_mask (size); + } + else + priv = NULL; + break; + } + if (priv == NULL) + { + int count = glamor_glyph_size_to_count (size); + mask = glamor_glyph_count_to_mask (count); + pos = cache->evict & mask; + for (s = 0; s < count; s++) + { + GlyphPtr evicted = cache->glyphs[pos + s]; + if (evicted != NULL) + { + if (priv != NULL) + free (priv); + + priv = glamor_glyph_get_private (evicted); + glamor_glyph_set_private (evicted, NULL); + cache->glyphs[pos + s] = NULL; + } + } + } + /* And pick a new eviction position */ + cache->evict = rand () % GLYPH_CACHE_SIZE; + } + + if (priv == NULL) + { + priv = malloc (sizeof (struct glamor_glyph)); + if (priv == NULL) + return NULL; + } + + glamor_glyph_set_private (glyph, priv); + cache->glyphs[pos] = glyph; + + priv->cache = cache; + priv->size = size; + priv->pos = pos; + s = + pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * + (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE)); + priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE; + priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE; + for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) + { + if (pos & 1) + priv->x += s; + if (pos & 2) + priv->y += s; + pos >>= 2; + } + + glamor_glyph_cache_upload_glyph (screen, cache, glyph, priv->x, priv->y); + + *out_x = priv->x; + *out_y = priv->y; + return cache->picture; +} + +static glamor_glyph_cache_result_t +glamor_buffer_glyph (ScreenPtr screen, + glamor_glyph_buffer_t * buffer, + GlyphPtr glyph, int x_glyph, int y_glyph) +{ + glamor_screen_private *glamor_screen = glamor_get_screen_private (screen); + unsigned int format = (GlyphPicture (glyph)[screen->myNum])->format; + glamor_composite_rect_t *rect; + PicturePtr source; + struct glamor_glyph *priv; + int x, y; + PicturePtr glyph_picture = GlyphPicture (glyph)[screen->myNum]; + glamor_glyph_cache_t *cache; + + if (PICT_FORMAT_BPP (format) == 1) + format = PICT_a8; + + cache = &glamor_screen->glyphCaches[PICT_FORMAT_RGB (glyph_picture->format) != 0]; + + if (buffer->source && buffer->source != cache->picture) + return GLAMOR_GLYPH_NEED_FLUSH; + + if (buffer->count == GLYPH_BUFFER_SIZE) + return GLAMOR_GLYPH_NEED_FLUSH; + + priv = glamor_glyph_get_private (glyph); + + if (priv) + { + rect = &buffer->rects[buffer->count++]; + rect->x_src = priv->x; + rect->y_src = priv->y; + if (buffer->source == NULL) buffer->source = priv->cache->picture; + } + else + { + source = glamor_glyph_cache (screen, glyph, &x, &y); + if (source != NULL) + { + rect = &buffer->rects[buffer->count++]; + rect->x_src = x; + rect->y_src = y; + if (buffer->source == NULL) buffer->source = source; + } + else + { + source = GlyphPicture (glyph)[screen->myNum]; + if (buffer->source && buffer->source != source) + return GLAMOR_GLYPH_NEED_FLUSH; + buffer->source = source; + + rect = &buffer->rects[buffer->count++]; + rect->x_src = 0; + rect->y_src = 0; + } + } + + rect->x_dst = x_glyph - glyph->info.x; + rect->y_dst = y_glyph - glyph->info.y; + rect->width = glyph->info.width; + rect->height = glyph->info.height; + + /* Couldn't find the glyph in the cache, use the glyph picture directly */ + + return GLAMOR_GLYPH_SUCCESS; +} + + +static void +glamor_glyphs_flush_mask (PicturePtr mask, glamor_glyph_buffer_t * buffer) +{ +#ifdef RENDER + glamor_composite_rects (PictOpAdd, buffer->source, NULL, mask, + buffer->count, buffer->rects); +#endif + buffer->count = 0; + buffer->source = NULL; +} + +static void +glamor_glyphs_via_mask (CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, + int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + PixmapPtr mask_pixmap = 0; + PicturePtr mask; + ScreenPtr screen = dst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int x_dst = list->xOff, y_dst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents = { 0, 0, 0, 0 }; + CARD32 component_alpha; + glamor_glyph_buffer_t buffer; + + GCPtr gc; + + glamor_glyph_extents (nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + + if (mask_format->depth == 1) + { + PictFormatPtr a8Format = PictureMatchFormat (screen, 8, PICT_a8); + + if (a8Format) + mask_format = a8Format; + } + + mask_pixmap = screen->CreatePixmap (screen, width, height, + mask_format->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!mask_pixmap) + return; + component_alpha = NeedsComponent (mask_format->format); + mask = CreatePicture (0, &mask_pixmap->drawable, + mask_format, CPComponentAlpha, + &component_alpha, serverClient, &error); + if (!mask) + { + screen->DestroyPixmap (mask_pixmap); + return; + } + gc = GetScratchGC (mask_pixmap->drawable.depth, screen); + ValidateGC (&mask_pixmap->drawable, gc); + glamor_fill (&mask_pixmap->drawable, gc, 0, 0, width, height); + FreeScratchGC (gc); + x = -extents.x1; + y = -extents.y1; + + buffer.count = 0; + buffer.source = NULL; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) + { + glyph = *glyphs++; + + if (glyph->info.width > 0 && glyph->info.height > 0 && + glamor_buffer_glyph (screen, &buffer, glyph, x, + y) == GLAMOR_GLYPH_NEED_FLUSH) + { + + glamor_glyphs_flush_mask (mask, &buffer); + + glamor_buffer_glyph (screen, &buffer, glyph, x, y); + } + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + + if (buffer.count) + glamor_glyphs_flush_mask (mask, &buffer); + + x = extents.x1; + y = extents.y1; + CompositePicture (op, + src, + mask, + dst, + x_src + x - x_dst, + y_src + y - y_dst, 0, 0, x, y, width, height); + FreePicture (mask, 0); + screen->DestroyPixmap (mask_pixmap); +} + +static void +glamor_glyphs_flush_dst (CARD8 op, + PicturePtr src, + PicturePtr dst, + glamor_glyph_buffer_t * buffer, + INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst) +{ + int i; + glamor_composite_rect_t *rect = &buffer->rects[0]; + for (i = 0; i < buffer->count; i++, rect++) + { + rect->x_mask = rect->x_src; + rect->y_mask = rect->y_src; + rect->x_src = x_src + rect->x_dst - x_dst; + rect->y_src = y_src + rect->y_dst - y_dst; + } + + glamor_composite_rects (op, src, buffer->source, dst, + buffer->count, &buffer->rects[0]); + + buffer->count = 0; + buffer->source = NULL; +} + +static void +glamor_glyphs_to_dst (CARD8 op, + PicturePtr src, + PicturePtr dst, + INT16 x_src, + INT16 y_src, + int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + ScreenPtr screen = dst->pDrawable->pScreen; + int x = 0, y = 0; + int x_dst = list->xOff, y_dst = list->yOff; + int n; + GlyphPtr glyph; + glamor_glyph_buffer_t buffer; + + buffer.count = 0; + buffer.source = NULL; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) + { + glyph = *glyphs++; + + if (glyph->info.width > 0 && glyph->info.height > 0 && + glamor_buffer_glyph (screen, &buffer, glyph, x, + y) == GLAMOR_GLYPH_NEED_FLUSH) + { + glamor_glyphs_flush_dst (op, src, dst, + &buffer, x_src, y_src, x_dst, y_dst); + glamor_buffer_glyph (screen, &buffer, glyph, x, y); + } + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + + if (buffer.count) + glamor_glyphs_flush_dst (op, src, dst, &buffer, + x_src, y_src, x_dst, y_dst); } void -glamor_glyphs(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +glamor_glyphs (CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - PicturePtr picture; - PixmapPtr mask_pixmap = 0; - PicturePtr mask; - ScreenPtr screen = dst->pDrawable->pScreen; - int width = 0, height = 0; - int x, y; - int x_dst = list->xOff, y_dst = list->yOff; - int n; - GlyphPtr glyph; - int error; - BoxRec extents = { 0, 0, 0, 0 }; - CARD32 component_alpha; - glamor_glyph_buffer_t buffer; + /* If we don't have a mask format but all the glyphs have the same format + * and don't intersect, use the glyph format as mask format for the full + * benefits of the glyph cache. + */ + if (!mask_format) + { + Bool same_format = TRUE; + int i; - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ - if (!mask_format) { - Bool same_format = TRUE; - int i; + mask_format = list[0].format; - mask_format = list[0].format; - - for (i = 0; i < nlist; i++) { - if (mask_format->format != list[i].format->format) { - same_format = FALSE; - break; + for (i = 0; i < nlist; i++) + { + if (mask_format->format != list[i].format->format) + { + same_format = FALSE; + break; } } - if (!same_format || (mask_format->depth != 1 && - glamor_glyphs_intersect(nlist, list, - glyphs))) { - mask_format = NULL; + if (!same_format || (mask_format->depth != 1 && + glamor_glyphs_intersect (nlist, list, glyphs))) + { + mask_format = NULL; } } - if (mask_format) { - GCPtr gc; - xRectangle rect; - - glamor_glyph_extents(nlist, list, glyphs, &extents); - - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) - return; - width = extents.x2 - extents.x1; - height = extents.y2 - extents.y1; - - if (mask_format->depth == 1) { - PictFormatPtr a8Format = - PictureMatchFormat(screen, 8, PICT_a8); - - if (a8Format) - mask_format = a8Format; - } - - mask_pixmap = screen->CreatePixmap(screen, width, height, - mask_format->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!mask_pixmap) - return; - component_alpha = NeedsComponent(mask_format->format); - mask = CreatePicture(0, &mask_pixmap->drawable, - mask_format, CPComponentAlpha, - &component_alpha, serverClient, &error); - if (!mask) { - screen->DestroyPixmap(mask_pixmap); - return; - } - gc = GetScratchGC(mask_pixmap->drawable.depth, screen); - ValidateGC(&mask_pixmap->drawable, gc); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - gc->ops->PolyFillRect(&mask_pixmap->drawable, gc, 1, &rect); - FreeScratchGC(gc); - x = -extents.x1; - y = -extents.y1; - } else { - mask = dst; - x = 0; - y = 0; - } - buffer.count = 0; - buffer.source = NULL; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - while (n--) { - glyph = *glyphs++; - picture = GlyphPicture(glyph)[screen->myNum]; - - if (glyph->info.width > 0 && glyph->info.height > 0 && - glamor_buffer_glyph(screen, &buffer, glyph, x, - y) == GLAMOR_GLYPH_NEED_FLUSH) { - if (mask_format) - glamor_glyphs_to_mask(mask, &buffer); - else - glamor_glyphs_to_dst(op, src, dst, - &buffer, x_src, y_src, - x_dst, y_dst); - - glamor_buffer_glyph(screen, &buffer, glyph, x, y); - } - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - } - - if (buffer.count) { - if (mask_format) - glamor_glyphs_to_mask(mask, &buffer); - else - glamor_glyphs_to_dst(op, src, dst, &buffer, - x_src, y_src, x_dst, y_dst); - } - - if (mask_format) { - x = extents.x1; - y = extents.y1; - CompositePicture(op, - src, - mask, - dst, - x_src + x - x_dst, - y_src + y - y_dst, 0, 0, x, y, width, height); - FreePicture(mask, 0); - screen->DestroyPixmap(mask_pixmap); - } + if (mask_format) + glamor_glyphs_via_mask (op, src, dst, mask_format, + x_src, y_src, nlist, list, glyphs); + else + glamor_glyphs_to_dst (op, src, dst, x_src, y_src, nlist, list, glyphs); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 4feb0048e..76e21ea1e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -138,38 +138,16 @@ typedef struct { INT16 height; } glamor_composite_rect_t; -typedef struct { - unsigned char sha1[20]; -} glamor_cached_glyph_t; +#define GLAMOR_NUM_GLYPH_CACHES 4 +#define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 typedef struct { - /* 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; - - /* 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 */ - - 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 */ + GlyphPtr *glyphs; + uint16_t count; + uint16_t evict; } glamor_glyph_cache_t; -#define GLAMOR_NUM_GLYPH_CACHES 4 enum glamor_vertex_type { GLAMOR_VERTEX_POS, @@ -268,6 +246,10 @@ typedef struct glamor_screen_private { glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; + + glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; + Bool glyph_cache_initialized; + } glamor_screen_private; typedef enum glamor_access { @@ -838,7 +820,6 @@ glamor_get_spans(DrawablePtr drawable, char *dst_start); /* glamor_glyphs.c */ -void glamor_glyphs_init(ScreenPtr screen); void glamor_glyphs_fini(ScreenPtr screen); void glamor_glyphs(CARD8 op, PicturePtr pSrc, @@ -888,7 +869,7 @@ void glamor_trapezoids(CARD8 op, int ntrap, xTrapezoid *traps); void glamor_init_composite_shaders(ScreenPtr screen); void glamor_composite_rects(CARD8 op, - PicturePtr src, PicturePtr dst, + PicturePtr src, PicturePtr mask, PicturePtr dst, int nrect, glamor_composite_rect_t *rects); /* glamor_tile.c */ @@ -999,7 +980,7 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -//#define GLAMOR_DELAYED_FILLING +#define GLAMOR_DELAYED_FILLING #include"glamor_utils.h" diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index bc6347883..258a09b9d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1405,7 +1405,7 @@ glamor_trapezoids(CARD8 op, void glamor_composite_rects(CARD8 op, - PicturePtr src, PicturePtr dst, + PicturePtr src, PicturePtr mask, PicturePtr dst, int nrect, glamor_composite_rect_t *rects) { int n; @@ -1414,7 +1414,7 @@ glamor_composite_rects(CARD8 op, ValidatePicture(src); ValidatePicture(dst); - if (glamor_composite_with_shader(op, src, NULL, dst, nrect, rects)) + if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) return; n = nrect; @@ -1423,10 +1423,10 @@ glamor_composite_rects(CARD8 op, while (n--) { CompositePicture(op, src, - NULL, + mask, dst, r->x_src, r->y_src, - 0, 0, + r->x_mask, r->y_mask, r->x_dst, r->y_dst, r->width, r->height); r++; From f08988455cd4f6339187e74df8edb5783b61f8fa Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 30 Aug 2011 18:24:53 +0800 Subject: [PATCH 206/462] glamor: Route UnrealizeGlyph to glamor_glyph_unrealize. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 3 +++ glamor/glamor_priv.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 53fe71d49..c0f9d51b5 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -359,6 +359,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) ps->CreatePicture = glamor_create_picture; glamor_priv->saved_destroy_picture = ps->DestroyPicture; ps->DestroyPicture = glamor_destroy_picture; + + glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph; + ps->UnrealizeGlyph = glamor_glyph_unrealize; #endif glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 76e21ea1e..325fa4343 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -205,6 +205,7 @@ typedef struct glamor_screen_private { TrianglesProcPtr saved_triangles; CreatePictureProcPtr saved_create_picture; DestroyPictureProcPtr saved_destroy_picture; + UnrealizeGlyphProcPtr saved_unrealize_glyph; int yInverted; int screen_fbo; @@ -828,6 +829,8 @@ void glamor_glyphs(CARD8 op, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); +void +glamor_glyph_unrealize (ScreenPtr screen, GlyphPtr glyph); /* glamor_setspans.c */ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted); From 7daf9af086624133d6c4857ed92d57ad2a492d86 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 31 Aug 2011 17:43:46 +0800 Subject: [PATCH 207/462] glamor: Let GLAMOR_DDX implicit GLAMOR. If user only enable GLAMOR_DDX, he must also want GLAMOR. Signed-off-by: Zhigang Gong --- configure.ac | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 82c845ba7..80daf828b 100644 --- a/configure.ac +++ b/configure.ac @@ -1772,7 +1772,11 @@ AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) dnl glamor -AM_CONDITIONAL([GLAMOR], [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes || test "x$GLAMOR" = xyes]) +if [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes] ; then + GLAMOR=yes +fi + +AM_CONDITIONAL([GLAMOR], [test "x$GLAMOR" = xyes]) AM_CONDITIONAL([GLAMOR_GLES2], [test "x$GLAMOR_GLES2" = xyes]) AM_CONDITIONAL([GLAMOR_DDX], [test "x$GLAMOR_DDX" = xyes]) From 0dff23d65b8bcec615f4c7a49efa7a5bf220b299 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 8 Sep 2011 14:05:46 +0800 Subject: [PATCH 208/462] glamor: Don't direct call to any gl functions. Create a new structure glamor_gl_dispatch to hold all the gl function's pointer and initialize them at run time , rather than use them directly. To do this is to avoid symbol conflicts. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor.c | 30 +++-- glamor/glamor.h | 2 + glamor/glamor_copyarea.c | 50 ++++---- glamor/glamor_core.c | 121 +++++++----------- glamor/glamor_egl.c | 21 ++- glamor/glamor_fill.c | 36 +++--- glamor/glamor_getspans.c | 5 +- glamor/glamor_gl_dispatch.c | 73 +++++++++++ glamor/glamor_gl_dispatch.h | 101 +++++++++++++++ glamor/glamor_pixmap.c | 227 +++++++++++++++++---------------- glamor/glamor_priv.h | 17 ++- glamor/glamor_putimage.c | 131 +++++++++---------- glamor/glamor_render.c | 146 +++++++++++---------- glamor/glamor_setspans.c | 19 ++- glamor/glamor_tile.c | 66 +++++----- hw/xfree86/glamor/glamor.c | 12 ++ hw/xfree86/glamor/glamor_ddx.h | 2 + 18 files changed, 638 insertions(+), 422 deletions(-) create mode 100644 glamor/glamor_gl_dispatch.c create mode 100644 glamor/glamor_gl_dispatch.h diff --git a/glamor/Makefile.am b/glamor/Makefile.am index fcde76503..8712e765a 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -43,4 +43,5 @@ libglamor_la_SOURCES = \ glamor_pixmap.c\ glamor_picture.c\ glamor_window.c\ + glamor_gl_dispatch.c\ glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index c0f9d51b5..ea4099ed2 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -59,7 +59,7 @@ glamor_get_drawable_pixmap(DrawablePtr drawable) return (PixmapPtr)drawable; } -static void +void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -111,6 +111,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, int type = GLAMOR_PIXMAP_TEXTURE; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (w > 32767 || h > 32767) return NullPixmap; @@ -141,6 +142,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv->container = pixmap; + pixmap_priv->glamor_priv = glamor_priv; if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) return pixmap; @@ -160,11 +162,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, } /* Create the texture used to store the pixmap's data. */ - glGenTextures(1, &tex); - 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); - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, + dispatch->glGenTextures(1, &tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); glamor_set_pixmap_texture(pixmap, w, h, tex); @@ -210,14 +212,16 @@ glamor_create_screen_pixmap(ScreenPtr screen, int w, int h, int depth, static Bool glamor_destroy_pixmap(PixmapPtr pixmap) { + glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (pixmap->refcnt == 1) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv->fb) - glDeleteFramebuffers(1, &pixmap_priv->fb); + dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); if (pixmap_priv->tex) - glDeleteTextures(1, &pixmap_priv->tex); + dispatch->glDeleteTextures(1, &pixmap_priv->tex); if (pixmap_priv->pbo) - glDeleteBuffers(1, &pixmap_priv->pbo); + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); dixFreePrivates(pixmap->devPrivates, PRIVATE_PIXMAP); } @@ -227,7 +231,8 @@ glamor_destroy_pixmap(PixmapPtr pixmap) static void glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask) { - glFlush(); + glamor_gl_dispatch *dispatch = data; + dispatch->glFlush(); } static void @@ -295,6 +300,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) goto fail; } + glamor_gl_dispatch_init(screen, &glamor_priv->dispatch, gl_version); #ifdef GLAMOR_GLES2 if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) { @@ -305,11 +311,11 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->has_pack_invert = glamor_gl_has_extension("GL_MESA_pack_invert"); glamor_priv->has_fbo_blit = glamor_gl_has_extension("GL_EXT_framebuffer_blit"); - glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); + glamor_priv->dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, glamor_wakeup_handler, - NULL)) { + (void*)&glamor_priv->dispatch)) { goto fail; } diff --git a/glamor/glamor.h b/glamor/glamor.h index 7a0e89923..e8719fb2f 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -52,10 +52,12 @@ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); extern _X_EXPORT Bool glamor_glyphs_init (ScreenPtr pScreen); +void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex); #ifdef GLAMOR_FOR_XORG extern _X_EXPORT Bool glamor_egl_init(ScrnInfoPtr scrn, int fd); extern _X_EXPORT Bool glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride); +extern _X_EXPORT Bool glamor_create_egl_pixmap_image(PixmapPtr pixmap, int handle, int stride); extern _X_EXPORT Bool glamor_close_egl_screen(ScreenPtr screen); extern _X_EXPORT void glamor_free_egl_screen(int scrnIndex, int flags); #endif diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 3e6e6b9fc..ec57520e8 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -46,6 +46,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); glamor_pixmap_private *src_pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; int dst_x_off, dst_y_off, src_x_off, src_y_off, i; if (!glamor_priv->has_fbo_blit) { @@ -78,14 +79,14 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, } glamor_validate_pixmap(dst_pixmap); - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); + dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); 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); src_y_off += dy; for (i = 0; i < nbox; i++) { if(glamor_priv->yInverted) { - glBlitFramebuffer((box[i].x1 + dx + src_x_off), + dispatch->glBlitFramebuffer((box[i].x1 + dx + src_x_off), (box[i].y1 + src_y_off), (box[i].x2 + dx + src_x_off), (box[i].y2 + src_y_off), @@ -101,7 +102,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, int flip_src_y1 = src_pixmap->drawable.height - (box[i].y2 + src_y_off); int flip_src_y2 = src_pixmap->drawable.height - (box[i].y1 + src_y_off); - glBlitFramebuffer(box[i].x1 + dx + src_x_off, + dispatch->glBlitFramebuffer(box[i].x1 + dx + src_x_off, flip_src_y1, box[i].x2 + dx + src_x_off, flip_src_y2, @@ -129,6 +130,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, { glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int i; @@ -162,7 +164,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, flush_needed = 1; if (gc) { - glamor_set_alu(gc->alu); + glamor_set_alu(dispatch, gc->alu); if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fail; if (gc->alu != GXcopy) { @@ -181,10 +183,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src, - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); @@ -192,25 +194,25 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dy += src_y_off; pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); #ifndef GLAMOR_GLES2 - glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glUseProgram(glamor_priv->finish_access_prog[0]); - glUniform1i(glamor_priv->finish_access_no_revert[0], 1); - glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0], 1); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); } else { - GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); + GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, src_pixmap_priv); } for (i = 0; i < nbox; i++) { @@ -230,24 +232,24 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, texcoords); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #ifndef GLAMOR_GLES2 - glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif } - glUseProgram(0); + dispatch->glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ if (flush_needed) - glFlush(); + dispatch->glFlush(); return TRUE; fail: - glamor_set_alu(GXcopy); + glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(dst_pixmap, ~0); return FALSE; } diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 3609600bc..2249ac800 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -54,49 +54,24 @@ glamor_get_drawable_location(const DrawablePtr drawable) return 'f'; } - -void -glamor_get_transform_uniform_locations(GLint prog, - glamor_transform_uniforms *uniform_locations) -{ - uniform_locations->x_bias = glGetUniformLocation(prog, "x_bias"); - uniform_locations->x_scale = glGetUniformLocation(prog, "x_scale"); - uniform_locations->y_bias = glGetUniformLocation(prog, "y_bias"); - uniform_locations->y_scale = glGetUniformLocation(prog, "y_scale"); -} - -/* We don't use a full matrix for our transformations because it's - * wasteful when all we want is to rescale to NDC and possibly do a flip - * if it's the front buffer. - */ -void -glamor_set_transform_for_pixmap(PixmapPtr pixmap, - glamor_transform_uniforms *uniform_locations) -{ - glUniform1f(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f); - glUniform1f(uniform_locations->x_scale, 2.0f / pixmap->drawable.width); - glUniform1f(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f); - glUniform1f(uniform_locations->y_scale, -2.0f / pixmap->drawable.height); -} - GLint -glamor_compile_glsl_prog(GLenum type, const char *source) +glamor_compile_glsl_prog(glamor_gl_dispatch *dispatch, GLenum type, const char *source) { GLint ok; GLint prog; - prog = glCreateShader(type); - glShaderSource(prog, 1, (const GLchar **)&source, NULL); - glCompileShader(prog); - glGetShaderiv(prog, GL_COMPILE_STATUS, &ok); + prog = dispatch->glCreateShader(type); + dispatch->glShaderSource(prog, 1, (const GLchar **)&source, NULL); + dispatch->glCompileShader(prog); + dispatch->glGetShaderiv(prog, GL_COMPILE_STATUS, &ok); if (!ok) { GLchar *info; GLint size; - glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); + dispatch->glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); info = malloc(size); - glGetShaderInfoLog(prog, size, NULL, info); + dispatch->glGetShaderInfoLog(prog, size, NULL, info); ErrorF("Failed to compile %s: %s\n", type == GL_FRAGMENT_SHADER ? "FS" : "VS", info); @@ -108,20 +83,20 @@ glamor_compile_glsl_prog(GLenum type, const char *source) } void -glamor_link_glsl_prog(GLint prog) +glamor_link_glsl_prog(glamor_gl_dispatch *dispatch, GLint prog) { GLint ok; - glLinkProgram(prog); - glGetProgramiv(prog, GL_LINK_STATUS, &ok); + dispatch->glLinkProgram(prog); + dispatch->glGetProgramiv(prog, GL_LINK_STATUS, &ok); if (!ok) { GLchar *info; GLint size; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); + dispatch->glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); info = malloc(size); - glGetProgramInfoLog(prog, size, NULL, info); + dispatch->glGetProgramInfoLog(prog, size, NULL, info); ErrorF("Failed to link: %s\n", info); FatalError("GLSL link failure\n"); @@ -140,6 +115,7 @@ void glamor_init_finish_access_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; const char *vs_source = "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" @@ -200,51 +176,51 @@ glamor_init_finish_access_shaders(ScreenPtr screen) GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; GLint sampler_uniform_location; - glamor_priv->finish_access_prog[0] = glCreateProgram(); - glamor_priv->finish_access_prog[1] = glCreateProgram(); + glamor_priv->finish_access_prog[0] = dispatch->glCreateProgram(); + glamor_priv->finish_access_prog[1] = dispatch->glCreateProgram(); - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source); - glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); - glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, fs_source); + dispatch->glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); + dispatch->glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); - avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source); - set_alpha_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, set_alpha_source); - glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); - glAttachShader(glamor_priv->finish_access_prog[1], set_alpha_prog); + avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); + set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, set_alpha_source); + dispatch->glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); + dispatch->glAttachShader(glamor_priv->finish_access_prog[1], set_alpha_prog); - glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[0]); - glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[1]); glamor_priv->finish_access_no_revert[0] = - glGetUniformLocation(glamor_priv->finish_access_prog[0], "no_revert"); + dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0], "no_revert"); glamor_priv->finish_access_swap_rb[0] = - glGetUniformLocation(glamor_priv->finish_access_prog[0], "swap_rb"); + dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0], "swap_rb"); sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[0]); - glUniform1i(sampler_uniform_location, 0); - glUniform1i(glamor_priv->finish_access_no_revert[0],1); - glUniform1i(glamor_priv->finish_access_swap_rb[0],0); - glUseProgram(0); + dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); + dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); + dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0],1); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0],0); + dispatch->glUseProgram(0); glamor_priv->finish_access_no_revert[1] = - glGetUniformLocation(glamor_priv->finish_access_prog[1], "no_revert"); + dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1], "no_revert"); glamor_priv->finish_access_swap_rb[1] = - glGetUniformLocation(glamor_priv->finish_access_prog[1], "swap_rb"); + dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1], "swap_rb"); sampler_uniform_location = - glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); - glUseProgram(glamor_priv->finish_access_prog[1]); - glUniform1i(glamor_priv->finish_access_no_revert[1],1); - glUniform1i(sampler_uniform_location, 0); - glUniform1i(glamor_priv->finish_access_swap_rb[1],0); - glUseProgram(0); + dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); + dispatch->glUseProgram(glamor_priv->finish_access_prog[1]); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[1],1); + dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1],0); + dispatch->glUseProgram(0); } @@ -254,6 +230,7 @@ glamor_finish_access(DrawablePtr drawable) 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); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return; @@ -264,10 +241,10 @@ glamor_finish_access(DrawablePtr drawable) if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); - glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); - glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); + dispatch->glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); + dispatch->glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); pixmap_priv->pbo_valid = FALSE; - glDeleteBuffers(1, &pixmap_priv->pbo); + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; } else { free(pixmap->devPrivate.ptr); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index bdb2da711..773f90e2e 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -54,6 +54,7 @@ #define GLAMOR_FOR_XORG #include +#include #define GLAMOR_VERSION_MAJOR 0 #define GLAMOR_VERSION_MINOR 1 @@ -84,6 +85,7 @@ struct glamor_screen_private { PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; + struct glamor_gl_dispatch *dispatch; }; int xf86GlamorEGLPrivateIndex = -1; @@ -127,10 +129,10 @@ _glamor_create_egl_screen_image(ScrnInfoPtr scrn, int width, int height, int str if (image == EGL_NO_IMAGE_KHR) return FALSE; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glamor->dispatch->glGenTextures(1, &texture); + glamor->dispatch->glBindTexture(GL_TEXTURE_2D, texture); + glamor->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glamor->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); @@ -296,3 +298,14 @@ glamor_free_egl_screen(int scrnIndex, int flags) free(glamor); } } + +Bool +glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, eglGetProcAddress)) + return FALSE; + glamor_egl->dispatch = dispatch; + return TRUE; +} diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 0b3d5fddf..7254167cb 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -105,6 +105,7 @@ void glamor_init_solid_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; const char *solid_vs = "attribute vec4 v_position;" "void main()\n" @@ -120,17 +121,17 @@ glamor_init_solid_shader(ScreenPtr screen) "}\n"; GLint fs_prog, vs_prog; - glamor_priv->solid_prog = glCreateProgram(); - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs); - glAttachShader(glamor_priv->solid_prog, vs_prog); - glAttachShader(glamor_priv->solid_prog, fs_prog); + glamor_priv->solid_prog = dispatch->glCreateProgram(); + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs); + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, solid_fs); + dispatch->glAttachShader(glamor_priv->solid_prog, vs_prog); + dispatch->glAttachShader(glamor_priv->solid_prog, fs_prog); - glBindAttribLocation(glamor_priv->solid_prog, GLAMOR_VERTEX_POS, "v_position"); - glamor_link_glsl_prog(glamor_priv->solid_prog); + dispatch->glBindAttribLocation(glamor_priv->solid_prog, GLAMOR_VERTEX_POS, "v_position"); + glamor_link_glsl_prog(dispatch, glamor_priv->solid_prog); glamor_priv->solid_color_uniform_location = - glGetUniformLocation(glamor_priv->solid_prog, "color"); + dispatch->glGetUniformLocation(glamor_priv->solid_prog, "color"); } Bool @@ -140,6 +141,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; int x1 = x; int x2 = x + width; int y1 = y; @@ -151,7 +153,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_fallback("dest %p has no fbo.\n", pixmap); goto fail; } - glamor_set_alu(alu); + glamor_set_alu(dispatch, alu); if (!glamor_set_planemask(pixmap, planemask)) { glamor_fallback("Failedto set planemask in glamor_solid.\n"); goto fail; @@ -178,24 +180,24 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); - glUseProgram(glamor_priv->solid_prog); + dispatch->glUseProgram(glamor_priv->solid_prog); - glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glUseProgram(0); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); return TRUE; fail: - glamor_set_alu(GXcopy); + glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); return FALSE; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index ba409dc23..224af1ba5 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -44,6 +44,7 @@ glamor_get_spans(DrawablePtr drawable, int no_alpha, no_revert; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; PixmapPtr temp_pixmap = NULL; int i; uint8_t *readpixels_dst = (uint8_t *)dst; @@ -79,14 +80,14 @@ glamor_get_spans(DrawablePtr drawable, 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, + dispatch->glReadPixels(points[i].x + x_off, (points[i].y + y_off), widths[i], 1, format, type, readpixels_dst); } else { - glReadPixels(points[i].x + x_off, + dispatch->glReadPixels(points[i].x + x_off, pixmap->drawable.height - 1 - (points[i].y + y_off), widths[i], 1, diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c new file mode 100644 index 000000000..823262494 --- /dev/null +++ b/glamor/glamor_gl_dispatch.c @@ -0,0 +1,73 @@ +#include "glamor_priv.h" + +#define INIT_FUNC(dst,func_name,get) \ + dst->func_name = get(#func_name); \ + if (dst->func_name == NULL) \ + { ErrorF("Failed to get fun %s", #func_name); \ + goto fail; } + +Bool +glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, + int gl_version, + void *(*get_proc_address)(const char*)) +{ + INIT_FUNC(dispatch, glMatrixMode, get_proc_address); + INIT_FUNC(dispatch, glLoadIdentity, get_proc_address); + INIT_FUNC(dispatch, glViewport, get_proc_address); + INIT_FUNC(dispatch, glRasterPos2i, get_proc_address); + INIT_FUNC(dispatch, glDrawArrays, get_proc_address); + INIT_FUNC(dispatch, glReadPixels, get_proc_address); + INIT_FUNC(dispatch, glDrawPixels, get_proc_address); + INIT_FUNC(dispatch, glPixelStorei, get_proc_address); + INIT_FUNC(dispatch, glTexParameteri, get_proc_address); + INIT_FUNC(dispatch, glTexImage2D, get_proc_address); + INIT_FUNC(dispatch, glGenTextures, get_proc_address); + INIT_FUNC(dispatch, glDeleteTextures, get_proc_address); + INIT_FUNC(dispatch, glBindTexture, get_proc_address); + INIT_FUNC(dispatch, glTexSubImage2D, get_proc_address); + INIT_FUNC(dispatch, glFlush, get_proc_address); + INIT_FUNC(dispatch, glGetIntegerv, get_proc_address); + INIT_FUNC(dispatch, glGetString, get_proc_address); + INIT_FUNC(dispatch, glScissor, get_proc_address); + INIT_FUNC(dispatch, glEnable, get_proc_address); + INIT_FUNC(dispatch, glDisable, get_proc_address); + INIT_FUNC(dispatch, glBlendFunc, get_proc_address); + INIT_FUNC(dispatch, glLogicOp, get_proc_address); + INIT_FUNC(dispatch, glActiveTexture, get_proc_address); + INIT_FUNC(dispatch, glGenBuffers, get_proc_address); + INIT_FUNC(dispatch, glBufferData, get_proc_address); + INIT_FUNC(dispatch, glMapBuffer, get_proc_address); + INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); + INIT_FUNC(dispatch, glBindBuffer, get_proc_address); + INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address); + INIT_FUNC(dispatch, glFramebufferTexture2D, get_proc_address); + INIT_FUNC(dispatch, glBindFramebuffer, get_proc_address); + INIT_FUNC(dispatch, glDeleteFramebuffers, get_proc_address); + INIT_FUNC(dispatch, glGenFramebuffers, get_proc_address); + INIT_FUNC(dispatch, glCheckFramebufferStatus, get_proc_address); + INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address); + INIT_FUNC(dispatch, glVertexAttribPointer, get_proc_address); + INIT_FUNC(dispatch, glDisableVertexAttribArray, get_proc_address); + INIT_FUNC(dispatch, glEnableVertexAttribArray, get_proc_address); + INIT_FUNC(dispatch, glBindAttribLocation, get_proc_address); + INIT_FUNC(dispatch, glLinkProgram, get_proc_address); + INIT_FUNC(dispatch, glShaderSource, get_proc_address); + + INIT_FUNC(dispatch, glUseProgram, get_proc_address); + INIT_FUNC(dispatch, glUniform1i, get_proc_address); + INIT_FUNC(dispatch, glUniform4f, get_proc_address); + INIT_FUNC(dispatch, glUniform4fv, get_proc_address); + INIT_FUNC(dispatch, glCreateProgram, get_proc_address); + INIT_FUNC(dispatch, glCreateShader, get_proc_address); + INIT_FUNC(dispatch, glCompileShader, get_proc_address); + INIT_FUNC(dispatch, glAttachShader, get_proc_address); + INIT_FUNC(dispatch, glGetShaderiv, get_proc_address); + INIT_FUNC(dispatch, glGetShaderInfoLog, get_proc_address); + INIT_FUNC(dispatch, glGetProgramiv, get_proc_address); + INIT_FUNC(dispatch, glGetProgramInfoLog, get_proc_address); + INIT_FUNC(dispatch, glGetUniformLocation, get_proc_address); + + return TRUE; +fail: + return FALSE; +} diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h new file mode 100644 index 000000000..c519667f6 --- /dev/null +++ b/glamor/glamor_gl_dispatch.h @@ -0,0 +1,101 @@ +typedef struct glamor_gl_dispatch { + /* Transformation functions */ + void (*glMatrixMode)(GLenum mode); + void (*glLoadIdentity)(void); + void (*glViewport)( GLint x, GLint y, + GLsizei width, GLsizei height ); + /* Drawing functions */ + void (*glRasterPos2i)( GLint x, GLint y ); + + /* Vertex Array */ + void (*glDrawArrays)( GLenum mode, GLint first, GLsizei count ); + + /* Raster functions */ + void (*glReadPixels)( GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid *pixels ); + + void (*glDrawPixels)( GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ); + void (*glPixelStorei)( GLenum pname, GLint param ); + /* Texture Mapping */ + + void (*glTexParameteri)( GLenum target, GLenum pname, GLint param ); + void (*glTexImage2D)( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ); + /* 1.1 */ + void (*glGenTextures)( GLsizei n, GLuint *textures ); + void (*glDeleteTextures)( GLsizei n, const GLuint *textures); + void (*glBindTexture)( GLenum target, GLuint texture ); + void (*glTexSubImage2D)( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ); + /* MISC */ + void (*glFlush)( void ); + void (*glGetIntegerv)( GLenum pname, GLint *params ); + const GLubyte * (*glGetString)( GLenum name ); + void (*glScissor)( GLint x, GLint y, GLsizei width, GLsizei height); + void (*glEnable)( GLenum cap ); + void (*glDisable)( GLenum cap ); + void (*glBlendFunc)( GLenum sfactor, GLenum dfactor ); + void (*glLogicOp)( GLenum opcode ); + + /* 1.3 */ + void (*glActiveTexture)( GLenum texture ); + + /* GL Extentions */ + void (*glGenBuffers) (GLsizei n, GLuint *buffers); + void (*glBufferData) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); + GLvoid* (*glMapBuffer) (GLenum target, GLenum access); + GLboolean (*glUnmapBuffer) (GLenum target); + void (*glBindBuffer) (GLenum target, GLuint buffer); + void (*glDeleteBuffers) (GLsizei n, const GLuint *buffers); + + void (*glFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void (*glBindFramebuffer) (GLenum target, GLuint framebuffer); + void (*glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers); + void (*glGenFramebuffers) (GLsizei n, GLuint *framebuffers); + GLenum (*glCheckFramebufferStatus) (GLenum target); + void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + + void (*glVertexAttribPointer) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + void (*glDisableVertexAttribArray) (GLuint index); + void (*glEnableVertexAttribArray) (GLuint index); + void (*glBindAttribLocation) (GLuint program, GLuint index, const GLchar *name); + + void (*glLinkProgram) (GLuint program); + void (*glShaderSource) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); + void (*glUseProgram) (GLuint program); + void (*glUniform1i) (GLint location, GLint v0); + void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void (*glUniform4fv) (GLint location, GLsizei count, const GLfloat *value); + GLuint (*glCreateProgram) (void); + GLuint (*glCreateShader) (GLenum type); + void (*glCompileShader) (GLuint shader); + void (*glAttachShader) (GLuint program, GLuint shader); + void (*glGetShaderiv) (GLuint shader, GLenum pname, GLint *params); + void (*glGetShaderInfoLog) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); + void (*glGetProgramiv) (GLuint program, GLenum pname, GLint *params); + void (*glGetProgramInfoLog) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); + GLint (*glGetUniformLocation) (GLuint program, const GLchar *name); + +}glamor_gl_dispatch; + +Bool +glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, + int gl_version, + void *(*get_proc_address)(const char*)); + + +Bool +glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version); + + + diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 15fc01448..28ad57a4d 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -31,12 +31,13 @@ static void _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, glamor_pixmap_private *pixmap_priv) { + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; GLfloat vertices[8]; - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glUseProgram(glamor_priv->solid_prog); - glUniform4fv(glamor_priv->solid_color_uniform_location, + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(glamor_priv->solid_prog); + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, 1, pixmap_priv->pending_op.fill.color4fv); vertices[0] = -1; vertices[1] = -1; @@ -46,9 +47,9 @@ _glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, vertices[5] = 1; vertices[6] = -1; vertices[7] = 1; - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glUseProgram(0); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } @@ -83,14 +84,15 @@ glamor_validate_pixmap(PixmapPtr pixmap) void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) { - glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); #ifndef GLAMOR_GLES2 - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + dispatch->glMatrixMode(GL_PROJECTION); + dispatch->glLoadIdentity(); + dispatch->glMatrixMode(GL_MODELVIEW); + dispatch->glLoadIdentity(); #endif - glViewport(0, 0, + dispatch->glViewport(0, 0, pixmap_priv->container->drawable.width, pixmap_priv->container->drawable.height); @@ -130,59 +132,59 @@ glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) void -glamor_set_alu(unsigned char alu) +glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) { #ifndef GLAMOR_GLES2 if (alu == GXcopy) { - glDisable(GL_COLOR_LOGIC_OP); + dispatch->glDisable(GL_COLOR_LOGIC_OP); return; } - glEnable(GL_COLOR_LOGIC_OP); + dispatch->glEnable(GL_COLOR_LOGIC_OP); switch (alu) { case GXclear: - glLogicOp(GL_CLEAR); + dispatch->glLogicOp(GL_CLEAR); break; case GXand: - glLogicOp(GL_AND); + dispatch->glLogicOp(GL_AND); break; case GXandReverse: - glLogicOp(GL_AND_REVERSE); + dispatch->glLogicOp(GL_AND_REVERSE); break; case GXandInverted: - glLogicOp(GL_AND_INVERTED); + dispatch->glLogicOp(GL_AND_INVERTED); break; case GXnoop: - glLogicOp(GL_NOOP); + dispatch->glLogicOp(GL_NOOP); break; case GXxor: - glLogicOp(GL_XOR); + dispatch->glLogicOp(GL_XOR); break; case GXor: - glLogicOp(GL_OR); + dispatch->glLogicOp(GL_OR); break; case GXnor: - glLogicOp(GL_NOR); + dispatch->glLogicOp(GL_NOR); break; case GXequiv: - glLogicOp(GL_EQUIV); + dispatch->glLogicOp(GL_EQUIV); break; case GXinvert: - glLogicOp(GL_INVERT); + dispatch->glLogicOp(GL_INVERT); break; case GXorReverse: - glLogicOp(GL_OR_REVERSE); + dispatch->glLogicOp(GL_OR_REVERSE); break; case GXcopyInverted: - glLogicOp(GL_COPY_INVERTED); + dispatch->glLogicOp(GL_COPY_INVERTED); break; case GXorInverted: - glLogicOp(GL_OR_INVERTED); + dispatch->glLogicOp(GL_OR_INVERTED); break; case GXnand: - glLogicOp(GL_NAND); + dispatch->glLogicOp(GL_NAND); break; case GXset: - glLogicOp(GL_SET); + dispatch->glLogicOp(GL_SET); break; default: FatalError("unknown logic op\n"); @@ -206,6 +208,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; unsigned int stride, row_length; void *texels; GLenum iformat; @@ -231,24 +234,24 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { texels = NULL; - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->pbo); + dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->pbo); } else texels = pixmap->devPrivate.ptr; - glTexImage2D(GL_TEXTURE_2D, + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, pixmap->drawable.width, @@ -271,6 +274,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; static float vertices[8] = {-1, -1, 1, -1, 1, 1, @@ -303,41 +307,41 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, ptexcoords = texcoords_inv; /* Slow path, we need to flip y or wire alpha to 1. */ - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), ptexcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glGenTextures(1, &tex); + dispatch->glGenTextures(1, &tex); __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->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); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); #ifndef GLAMOR_GLES2 - glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); - glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],0); + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],0); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); #ifndef GLAMOR_GLES2 - glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - glUseProgram(0); - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glDeleteTextures(1, &tex); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + dispatch->glUseProgram(0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDeleteTextures(1, &tex); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); } void @@ -345,16 +349,18 @@ glamor_pixmap_ensure_fb(PixmapPtr pixmap) { int status; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + if (pixmap_priv->fb == 0) - glGenFramebuffers(1, &pixmap_priv->fb); + dispatch->glGenFramebuffers(1, &pixmap_priv->fb); assert(pixmap_priv->tex != 0); - glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - glFramebufferTexture2D(GL_FRAMEBUFFER, + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pixmap_priv->tex, 0); - status = glCheckFramebufferStatus (GL_FRAMEBUFFER); + status = dispatch->glCheckFramebufferStatus (GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { const char *str; switch (status) { @@ -387,6 +393,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) int need_fbo; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!glamor_check_fbo_size(glamor_priv, pixmap->drawable.width , pixmap->drawable.height) || !glamor_check_fbo_depth(pixmap->drawable.depth)) { @@ -404,13 +411,13 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) need_fbo = 0; if (pixmap_priv->tex == 0) - glGenTextures(1, &pixmap_priv->tex); + dispatch->glGenTextures(1, &pixmap_priv->tex); if (need_fbo) { - glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - 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, + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixmap->drawable.width, pixmap->drawable.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glamor_pixmap_ensure_fb(pixmap); @@ -498,6 +505,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, ScreenPtr screen; PixmapPtr temp_pixmap; glamor_pixmap_private *temp_pixmap_priv; + glamor_gl_dispatch *dispatch; static float vertices[8] = {-1, -1, 1, -1, 1, 1, @@ -513,6 +521,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, glamor_priv = glamor_get_screen_private(screen); source_priv = glamor_get_pixmap_private(source); + dispatch = &glamor_priv->dispatch; if (*format == GL_BGRA) { *format = GL_RGBA; swap_rb = 1; @@ -527,36 +536,35 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); - glTexImage2D(GL_TEXTURE_2D, 0, *format, source->drawable.width, + dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, source->drawable.width, source->drawable.height, 0, *format, *type, NULL); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, source_priv->tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); - glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); - glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glUseProgram(0); - glFlush(); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); return temp_pixmap; } @@ -583,6 +591,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -641,43 +650,43 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); } else { - glPixelStorei(GL_PACK_ALIGNMENT, 4); - // glPixelStorei(GL_PACK_ROW_LENGTH, 0); + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); + // dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, 0); } - if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); - glPixelStorei(GL_PACK_INVERT_MESA, 1); + dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); } if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { if (pixmap_priv->pbo == 0) - glGenBuffers (1, &pixmap_priv->pbo); - glBindBuffer (GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); - glBufferData (GL_PIXEL_PACK_BUFFER, + dispatch->glGenBuffers (1, &pixmap_priv->pbo); + dispatch->glBindBuffer (GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); + dispatch->glBufferData (GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, NULL, gl_usage); - glReadPixels (0, 0, + dispatch->glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); - data = glMapBuffer (GL_PIXEL_PACK_BUFFER, gl_access); + data = dispatch->glMapBuffer (GL_PIXEL_PACK_BUFFER, gl_access); pixmap_priv->pbo_valid = TRUE; if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); - glPixelStorei(GL_PACK_INVERT_MESA, 0); + dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 0); } - glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); + dispatch->glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); + } else { if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) type = GL_UNSIGNED_SHORT_5_5_5_1; - glReadPixels (0, 0, + dispatch->glReadPixels (0, 0, pixmap->drawable.width, pixmap->drawable.height, format, type, data); } @@ -686,32 +695,31 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) assert(data); if (access != GLAMOR_ACCESS_WO) { if (pixmap_priv->pbo == 0) - glGenBuffers(1, &pixmap_priv->pbo); - glBindBuffer(GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); - glBufferData(GL_PIXEL_PACK_BUFFER, + dispatch->glGenBuffers(1, &pixmap_priv->pbo); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, NULL, GL_STREAM_READ); - glReadPixels (0, 0, row_length, pixmap->drawable.height, + dispatch->glReadPixels (0, 0, row_length, pixmap->drawable.height, format, type, 0); - read = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); + read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); for (y = 0; y < pixmap->drawable.height; y++) memcpy(data + y * stride, read + (pixmap->drawable.height - y - 1) * stride, stride); - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); pixmap_priv->pbo_valid = FALSE; - glDeleteBuffers(1, &pixmap_priv->pbo); + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->pbo = 0; } } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); done: pixmap->devPrivate.ptr = data; if (temp_pixmap) { - glFlush(); (*screen->DestroyPixmap)(temp_pixmap); } @@ -724,14 +732,15 @@ static void _glamor_destroy_upload_pixmap(PixmapPtr pixmap) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; assert(pixmap_priv->gl_fbo == 0); if (pixmap_priv->fb) - glDeleteFramebuffers(1, &pixmap_priv->fb); + dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); if (pixmap_priv->tex) - glDeleteTextures(1, &pixmap_priv->tex); + dispatch->glDeleteTextures(1, &pixmap_priv->tex); if (pixmap_priv->pbo) - glDeleteBuffers(1, &pixmap_priv->pbo); + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 325fa4343..0cbc258f3 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -178,6 +178,8 @@ enum shader_in { SHADER_IN_COUNT, }; +#include "glamor_gl_dispatch.h" + struct glamor_screen_private; struct glamor_pixmap_private; typedef void (*glamor_pixmap_validate_function_t)(struct glamor_screen_private*, @@ -251,6 +253,7 @@ typedef struct glamor_screen_private { glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; Bool glyph_cache_initialized; + struct glamor_gl_dispatch dispatch; } glamor_screen_private; typedef enum glamor_access { @@ -310,18 +313,18 @@ typedef struct glamor_pixmap_private { PictFormatShort pict_format; glamor_pending_op pending_op; PixmapPtr container; + glamor_screen_private *glamor_priv; } glamor_pixmap_private; -#define GLAMOR_CHECK_PENDING_FILL(_glamor_priv_, _pixmap_priv_) do \ +#define GLAMOR_CHECK_PENDING_FILL(_dispatch_, _glamor_priv_, _pixmap_priv_) do \ { \ if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ - glUseProgram(_glamor_priv_->solid_prog); \ - glUniform4fv(_glamor_priv_->solid_color_uniform_location, 1, \ + _dispatch_->glUseProgram(_glamor_priv_->solid_prog); \ + _dispatch_->glUniform4fv(_glamor_priv_->solid_color_uniform_location, 1, \ _pixmap_priv_->pending_op.fill.color4fv); \ } \ } while(0) - /* * Pixmap dynamic status, used by dynamic upload feature. * @@ -752,8 +755,8 @@ Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, unsigned char alu, unsigned long planemask, unsigned long fg_pixel, unsigned long bg_pixel, int stipple_x, int stipple_y); -GLint glamor_compile_glsl_prog(GLenum type, const char *source); -void glamor_link_glsl_prog(GLint prog); +GLint glamor_compile_glsl_prog(glamor_gl_dispatch *dispatch, GLenum type, const char *source); +void glamor_link_glsl_prog(glamor_gl_dispatch *dispatch, GLint prog); void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, GLfloat *color); @@ -770,7 +773,7 @@ PixmapPtr glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, GLenum *type, int no_alpha, int no_revert); -void glamor_set_alu(unsigned char alu); +void glamor_set_alu(struct glamor_gl_dispatch * dispatch, unsigned char alu); Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); void glamor_get_transform_uniform_locations(GLint prog, glamor_transform_uniforms *uniform_locations); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index a7a6186ee..cdcde5e7e 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -67,25 +67,25 @@ glamor_init_putimage_shaders(ScreenPtr screen) if (!GLEW_ARB_fragment_shader) return; - prog = glCreateProgram(); + prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xybitmap_vs); fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xybitmap_fs); - glAttachShader(prog, vs_prog); - glAttachShader(prog, fs_prog); + dispatch->glAttachShader(prog, vs_prog); + dispatch->glAttachShader(prog, fs_prog); glamor_link_glsl_prog(prog); - glUseProgram(prog); - sampler_uniform_location = glGetUniformLocation(prog, "bitmap_sampler"); - glUniform1i(sampler_uniform_location, 0); + dispatch->glUseProgram(prog); + sampler_uniform_location = dispatch->glGetUniformLocation(prog, "bitmap_sampler"); + dispatch->glUniform1i(sampler_uniform_location, 0); glamor_priv->put_image_xybitmap_fg_uniform_location = - glGetUniformLocation(prog, "fg"); + dispatch->glGetUniformLocation(prog, "fg"); glamor_priv->put_image_xybitmap_bg_uniform_location = - glGetUniformLocation(prog, "bg"); + dispatch->glGetUniformLocation(prog, "bg"); glamor_get_transform_uniform_locations(prog, &glamor_priv->put_image_xybitmap_transform); glamor_priv->put_image_xybitmap_prog = prog; - glUseProgram(0); + dispatch->glUseProgram(0); #endif } @@ -162,42 +162,42 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; - glUseProgram(glamor_priv->put_image_xybitmap_prog); + dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog); glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); - glUniform4fv(glamor_priv->put_image_xybitmap_fg_uniform_location, + dispatch->glUniform4fv(glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg); glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); - glUniform4fv(glamor_priv->put_image_xybitmap_bg_uniform_location, + dispatch->glUniform4fv(glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); - glGenTextures(1, &tex); - glActiveTexture(GL_TEXTURE0); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, + dispatch->glGenTextures(1, &tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); + dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glEnable(GL_TEXTURE_2D); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + dispatch->glEnable(GL_TEXTURE_2D); /* Now that we've set up our bitmap texture and the shader, shove * the destination rectangle through the cliprects and run the * shader on the resulting fragments. */ - glVertexPointer(2, GL_FLOAT, 0, dest_coords); - glEnableClientState(GL_VERTEX_ARRAY); - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords); + dispatch->glEnableClientState(GL_VERTEX_ARRAY); + dispatch->glClientActiveTexture(GL_TEXTURE0); + dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); + dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_SCISSOR_TEST); + dispatch->glEnable(GL_SCISSOR_TEST); clip = fbGetCompositeClip(gc); for (nbox = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); @@ -220,20 +220,20 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, if (x1 >= x2 || y1 >= y2) continue; - glScissor(box->x1, + dispatch->glScissor(box->x1, y_flip(pixmap, box->y1), box->x2 - box->x1, box->y2 - box->y1); - glDrawArrays(GL_QUADS, 0, 4); + dispatch->glDrawArrays(GL_QUADS, 0, 4); } - glDisable(GL_SCISSOR_TEST); + dispatch->glDisable(GL_SCISSOR_TEST); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); - glDeleteTextures(1, &tex); - glDisable(GL_TEXTURE_2D); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + dispatch->glDeleteTextures(1, &tex); + dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisableClientState(GL_VERTEX_ARRAY); + dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY); return; glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); @@ -254,6 +254,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, { glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); GLenum type, format, iformat; @@ -285,7 +286,7 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (!glamor_set_planemask(pixmap, gc->planemask)) { goto fail; } - glamor_set_alu(gc->alu); + glamor_set_alu(dispatch, gc->alu); if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, @@ -301,29 +302,29 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, /* XXX consider to reuse a function to do the following work. */ glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / pixmap->drawable.bitsPerPixel); } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); -// glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +// dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } - glGenTextures(1, &tex); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glGenTextures(1, &tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { iformat = format; } @@ -331,19 +332,19 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, iformat = GL_RGBA; } - glTexImage2D(GL_TEXTURE_2D, 0, iformat, + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); #ifndef GLAMOR_GLES2 - glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); - glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], 0); + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], 0); x += drawable->x; y += drawable->y; @@ -388,19 +389,19 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_priv->yInverted, vertices); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } #ifndef GLAMOR_GLES2 - glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - glUseProgram(0); - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glDeleteTextures(1, &tex); + dispatch->glUseProgram(0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDeleteTextures(1, &tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glamor_set_alu(GXcopy); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); return; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 258a09b9d..d649c9813 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -68,7 +68,7 @@ static struct blendinfo composite_op_info[] = { }; static GLuint -glamor_create_composite_fs(struct shader_key *key) +glamor_create_composite_fs(glamor_gl_dispatch *dispatch, struct shader_key *key) { const char *source_solid_fetch = GLAMOR_DEFAULT_PRECISION @@ -200,14 +200,14 @@ glamor_create_composite_fs(struct shader_key *key) in); - prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source); + prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, source); free(source); return prog; } static GLuint -glamor_create_composite_vs(struct shader_key *key) +glamor_create_composite_vs(glamor_gl_dispatch *dispatch, struct shader_key *key) { const char *main_opening = "attribute vec4 v_position;\n" @@ -242,7 +242,7 @@ glamor_create_composite_vs(struct shader_key *key) mask_coords_setup, main_closing); - prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, source); + prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, source); free(source); return prog; @@ -254,45 +254,47 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, { GLuint vs, fs, prog; GLint source_sampler_uniform_location, mask_sampler_uniform_location; + glamor_screen_private *glamor = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor->dispatch; - vs = glamor_create_composite_vs(key); + vs = glamor_create_composite_vs(dispatch, key); if (vs == 0) return; - fs = glamor_create_composite_fs(key); + fs = glamor_create_composite_fs(dispatch, key); if (fs == 0) return; - prog = glCreateProgram(); - glAttachShader(prog, vs); - glAttachShader(prog, fs); + prog = dispatch->glCreateProgram(); + dispatch->glAttachShader(prog, vs); + dispatch->glAttachShader(prog, fs); - glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); - glamor_link_glsl_prog(prog); + glamor_link_glsl_prog(dispatch, prog); shader->prog = prog; - glUseProgram(prog); + dispatch->glUseProgram(prog); if (key->source == SHADER_SOURCE_SOLID) { - shader->source_uniform_location = glGetUniformLocation(prog, + shader->source_uniform_location = dispatch->glGetUniformLocation(prog, "source"); } else { - source_sampler_uniform_location = glGetUniformLocation(prog, + source_sampler_uniform_location = dispatch->glGetUniformLocation(prog, "source_sampler"); - glUniform1i(source_sampler_uniform_location, 0); + dispatch->glUniform1i(source_sampler_uniform_location, 0); } if (key->mask != SHADER_MASK_NONE) { if (key->mask == SHADER_MASK_SOLID) { - shader->mask_uniform_location = glGetUniformLocation(prog, + shader->mask_uniform_location = dispatch->glGetUniformLocation(prog, "mask"); } else { - mask_sampler_uniform_location = glGetUniformLocation(prog, + mask_sampler_uniform_location = dispatch->glGetUniformLocation(prog, "mask_sampler"); - glUniform1i(mask_sampler_uniform_location, 1); + dispatch->glUniform1i(mask_sampler_uniform_location, 1); } } } @@ -336,6 +338,8 @@ glamor_set_composite_op(ScreenPtr screen, { GLenum source_blend, dest_blend; struct blendinfo *op_info; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (op >= ARRAY_SIZE(composite_op_info)) { glamor_fallback("unsupported render op %d \n", op); @@ -370,10 +374,10 @@ glamor_set_composite_op(ScreenPtr screen, } if (source_blend == GL_ONE && dest_blend == GL_ZERO) { - glDisable(GL_BLEND); + dispatch->glDisable(GL_BLEND); } else { - glEnable(GL_BLEND); - glBlendFunc(source_blend, dest_blend); + dispatch->glEnable(GL_BLEND); + dispatch->glBlendFunc(source_blend, dest_blend); } return TRUE; } @@ -382,50 +386,52 @@ 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); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + dispatch->glActiveTexture(GL_TEXTURE0 + unit); + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); switch (picture->repeatType) { case RepeatNone: #ifndef GLAMOR_GLES2 /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); #endif break; case RepeatNormal: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + dispatch->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); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + dispatch->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); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + dispatch->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); + dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->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); + dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; } #ifndef GLAMOR_GLES2 - glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif } static void -glamor_set_composite_solid(float *color, GLint uniform_location) +glamor_set_composite_solid(glamor_gl_dispatch *dispatch, float *color, GLint uniform_location) { - glUniform4fv(uniform_location, 1, color); + dispatch->glUniform4fv(uniform_location, 1, color); } static int @@ -525,6 +531,7 @@ static void glamor_setup_composite_vbo(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; glamor_priv->vb_stride = 2 * sizeof(float); if (glamor_priv->has_source_coords) @@ -532,27 +539,27 @@ glamor_setup_composite_vbo(ScreenPtr screen) if (glamor_priv->has_mask_coords) glamor_priv->vb_stride += 2 * sizeof(float); - glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset)); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); if (glamor_priv->has_source_coords) { - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset + 2 * sizeof(float))); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); } if (glamor_priv->has_mask_coords) { - glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, (void *)((long)glamor_priv->vbo_offset + (glamor_priv->has_source_coords ? 4 : 2) * sizeof(float))); - glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); } } @@ -586,13 +593,13 @@ static void glamor_flush_composite_rects(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!glamor_priv->render_nr_verts) return; - glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, glamor_priv->vb, + dispatch->glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, glamor_priv->vb, GL_STREAM_DRAW); - glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts); + dispatch->glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts); glamor_reset_composite_vbo(screen); } @@ -603,6 +610,7 @@ glamor_emit_composite_rect(ScreenPtr screen, const float *dst_coords) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (glamor_priv->vbo_offset + 6 * glamor_priv->vb_stride > glamor_priv->vbo_size) @@ -612,7 +620,7 @@ glamor_emit_composite_rect(ScreenPtr screen, if (glamor_priv->vbo_offset == 0) { if (glamor_priv->vbo == 0) - glGenBuffers(1, &glamor_priv->vbo); + dispatch->glGenBuffers(1, &glamor_priv->vbo); glamor_setup_composite_vbo(screen); } @@ -700,6 +708,7 @@ glamor_composite_with_shader(CARD8 op, { ScreenPtr screen = dest->pDrawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; glamor_pixmap_private *source_pixmap_priv = NULL; @@ -914,17 +923,17 @@ glamor_composite_with_shader(CARD8 op, goto fail; } - glUseProgram(shader->prog); + dispatch->glUseProgram(shader->prog); if (key.source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(source_solid_color, shader->source_uniform_location); + glamor_set_composite_solid(dispatch, source_solid_color, 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_solid_color, shader->mask_uniform_location); + glamor_set_composite_solid(dispatch, mask_solid_color, shader->mask_uniform_location); } else { glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); } @@ -1042,19 +1051,19 @@ glamor_composite_with_shader(CARD8 op, } glamor_flush_composite_rects(screen); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); REGION_UNINIT(dst->pDrawable->pScreen, ®ion); - glDisable(GL_BLEND); + dispatch->glDisable(GL_BLEND); #ifndef GLAMOR_GLES2 - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE1); + dispatch->glDisable(GL_TEXTURE_2D); #endif - glUseProgram(0); + dispatch->glUseProgram(0); if (saved_source_format) source->format = saved_source_format; return TRUE; @@ -1063,8 +1072,8 @@ glamor_composite_with_shader(CARD8 op, if (saved_source_format) source->format = saved_source_format; - glDisable(GL_BLEND); - glUseProgram(0); + dispatch->glDisable(GL_BLEND); + dispatch->glUseProgram(0); return FALSE; } @@ -1138,6 +1147,7 @@ glamor_composite(CARD8 op, int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; glamor_composite_rect_t rect; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; x_temp_src = x_source; y_temp_src = y_source; @@ -1257,8 +1267,8 @@ fail: dest->pDrawable->height, glamor_get_picture_location(dest)); - glUseProgram(0); - glDisable(GL_BLEND); + dispatch->glUseProgram(0); + dispatch->glDisable(GL_BLEND); if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO)) { diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 8b2676b4b..bb4bffdd9 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -36,7 +36,8 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - glamor_screen_private *glamor_priv; + glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; GLenum format, type; int no_alpha, no_revert, i; uint8_t *drawpixels_src = (uint8_t *)src; @@ -44,8 +45,6 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, BoxRec *pbox; int x_off, y_off; - glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { glamor_fallback("ES2 fallback.\n"); goto fail; @@ -69,7 +68,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_validate_pixmap(dest_pixmap); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; - glamor_set_alu(gc->alu); + glamor_set_alu(dispatch, gc->alu); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; @@ -82,14 +81,14 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, while (n--) { if (pbox->y1 > points[i].y) break; - glScissor(pbox->x1, + dispatch->glScissor(pbox->x1, points[i].y + y_off, pbox->x2 - pbox->x1, 1); - glEnable(GL_SCISSOR_TEST); - glRasterPos2i(points[i].x + x_off, + dispatch->glEnable(GL_SCISSOR_TEST); + dispatch->glRasterPos2i(points[i].x + x_off, points[i].y + y_off); - glDrawPixels(widths[i], + dispatch->glDrawPixels(widths[i], 1, format, type, drawpixels_src); @@ -97,8 +96,8 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } glamor_set_planemask(dest_pixmap, ~0); - glamor_set_alu(GXcopy); - glDisable(GL_SCISSOR_TEST); + glamor_set_alu(dispatch, GXcopy); + dispatch->glDisable(GL_SCISSOR_TEST); return; fail: diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index c184dac26..687cc6a41 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -40,6 +40,7 @@ void glamor_init_tile_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; const char *tile_vs = "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" @@ -60,21 +61,21 @@ glamor_init_tile_shader(ScreenPtr screen) GLint fs_prog, vs_prog; GLint sampler_uniform_location; - glamor_priv->tile_prog = glCreateProgram(); - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, tile_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs); - glAttachShader(glamor_priv->tile_prog, vs_prog); - glAttachShader(glamor_priv->tile_prog, fs_prog); + glamor_priv->tile_prog = dispatch->glCreateProgram(); + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs); + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, tile_fs); + dispatch->glAttachShader(glamor_priv->tile_prog, vs_prog); + dispatch->glAttachShader(glamor_priv->tile_prog, fs_prog); - glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_POS, "v_position"); - glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(glamor_priv->tile_prog); + dispatch->glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glamor_link_glsl_prog(dispatch, glamor_priv->tile_prog); sampler_uniform_location = - glGetUniformLocation(glamor_priv->tile_prog, "sampler"); - glUseProgram(glamor_priv->tile_prog); - glUniform1i(sampler_uniform_location, 0); - glUseProgram(0); + dispatch->glGetUniformLocation(glamor_priv->tile_prog, "sampler"); + dispatch->glUseProgram(glamor_priv->tile_prog); + dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUseProgram(0); } Bool @@ -85,6 +86,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; int x1 = x; int x2 = x + width; int y1 = y; @@ -135,33 +137,33 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_validate_pixmap(pixmap); pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - glamor_set_alu(alu); + glamor_set_alu(dispatch, alu); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - glUseProgram(glamor_priv->tile_prog); + dispatch->glUseProgram(glamor_priv->tile_prog); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); #ifndef GLAMOR_GLES2 - glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif glamor_set_normalize_tcoords(src_xscale, src_yscale, tile_x1, tile_y1, tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords); - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), source_texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); } else { - GLAMOR_CHECK_PENDING_FILL(glamor_priv, src_pixmap_priv); + GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, src_pixmap_priv); } glamor_set_normalize_vcoords(dst_xscale, dst_yscale, @@ -169,21 +171,21 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_priv->yInverted, vertices); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #ifndef GLAMOR_GLES2 - glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif } - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glUseProgram(0); - glamor_set_alu(GXcopy); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); return TRUE; diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 9c9be894f..90357d201 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -584,6 +584,18 @@ glamor_setup(pointer module, pointer opts, int *errmaj, int *errmin) } } +Bool +glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_screen_private *glamor_egl = glamor_get_screen_private(scrn); + if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, eglGetProcAddress)) + return FALSE; + glamor_egl->dispatch = dispatch; + return TRUE; +} + + static XF86ModuleVersionInfo glamor_version_info = { glamor_name, MODULEVENDORSTRING, diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index 6d9e410f0..2c14ca18e 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -16,6 +16,7 @@ #include #include +#include "glamor_gl_dispatch.h" struct glamor_screen_private { EGLDisplay display; EGLContext context; @@ -30,6 +31,7 @@ struct glamor_screen_private { PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; + struct glamor_gl_dispatch *dispatch; }; inline struct glamor_screen_private * From 2a9dfc963f610abfbf12d5efdf5ba5b3f55a4305 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 8 Sep 2011 15:14:43 +0800 Subject: [PATCH 209/462] glamor: Re-arrange some macros/definitions in header files. Signed-off-by: Zhigang Gong --- glamor/glamor_glext.h | 32 +++ glamor/glamor_priv.h | 491 +++--------------------------------------- glamor/glamor_utils.h | 380 ++++++++++++++++++++++++++++++++ 3 files changed, 445 insertions(+), 458 deletions(-) create mode 100644 glamor/glamor_glext.h diff --git a/glamor/glamor_glext.h b/glamor/glamor_glext.h new file mode 100644 index 000000000..f734d1313 --- /dev/null +++ b/glamor/glamor_glext.h @@ -0,0 +1,32 @@ +#ifdef GLAMOR_GLES2 + +#define GL_BGRA GL_BGRA_EXT +#define GL_COLOR_INDEX 0x1900 +#define GL_BITMAP 0x1A00 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 + +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_CLAMP_TO_BORDER 0x812D + +#define GL_READ_WRITE 0x88BA +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 + +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 + +#define GL_PACK_INVERT_MESA 0x8758 + +#endif diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0cbc258f3..5f82c7883 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -35,89 +35,26 @@ #include "glamor.h" -#ifdef GLAMOR_GLES2 -#define GL_BGRA GL_BGRA_EXT -#define GL_COLOR_INDEX 0x1900 -#define GL_BITMAP 0x1A00 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 - -#define GL_PIXEL_PACK_BUFFER 0x88EB -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#define GL_CLAMP_TO_BORDER 0x812D - -#define GL_READ_WRITE 0x88BA -#define GL_READ_ONLY 0x88B8 -#define GL_WRITE_ONLY 0x88B9 -#define GL_STREAM_DRAW 0x88E0 -#define GL_STREAM_READ 0x88E1 -#define GL_PACK_ROW_LENGTH 0x0D02 -#define GL_UNPACK_ROW_LENGTH 0x0CF2 - -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 - -#define GL_PACK_INVERT_MESA 0x8758 - -#define glMapBuffer(x, y) NULL -#define glUnmapBuffer(x) -#define glRasterPos2i(x,y) -#define glDrawPixels(x,y,z,a,b) - -#endif - #define GL_GLEXT_PROTOTYPES + #ifdef GLAMOR_GLES2 #include #include -#define GLAMOR_DEFAULT_PRECISION \ - "precision mediump float;\n" - +#define GLAMOR_DEFAULT_PRECISION "precision mediump float;\n" +#include "glamor_glext.h" #else #include #include - #define GLAMOR_DEFAULT_PRECISION #endif - #ifdef RENDER #include "glyphstr.h" #endif - #include "glamor_debug.h" -#define glamor_check_fbo_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \ - && (_w_) < _glamor_->max_fbo_size \ - && (_h_) < _glamor_->max_fbo_size) - -#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; -} glamor_transform_uniforms; - typedef struct glamor_composite_shader { GLuint prog; GLint dest_to_dest_uniform_location; @@ -138,16 +75,6 @@ typedef struct { INT16 height; } glamor_composite_rect_t; -#define GLAMOR_NUM_GLYPH_CACHES 4 -#define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 - -typedef struct { - PicturePtr picture; /* Where the glyphs of the cache are stored */ - GlyphPtr *glyphs; - uint16_t count; - uint16_t evict; -} glamor_glyph_cache_t; - enum glamor_vertex_type { GLAMOR_VERTEX_POS, @@ -178,8 +105,6 @@ enum shader_in { SHADER_IN_COUNT, }; -#include "glamor_gl_dispatch.h" - struct glamor_screen_private; struct glamor_pixmap_private; typedef void (*glamor_pixmap_validate_function_t)(struct glamor_screen_private*, @@ -191,6 +116,20 @@ enum glamor_gl_flavor { }; #define GLAMOR_CREATE_PIXMAP_CPU 0x100 + +#define GLAMOR_NUM_GLYPH_CACHES 4 +#define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 + +typedef struct { + PicturePtr picture; /* Where the glyphs of the cache are stored */ + GlyphPtr *glyphs; + uint16_t count; + uint16_t evict; +} glamor_glyph_cache_t; + + +#include "glamor_gl_dispatch.h" + typedef struct glamor_screen_private { CloseScreenProcPtr saved_close_screen; CreateGCProcPtr saved_create_gc; @@ -235,7 +174,6 @@ typedef struct glamor_screen_private { /* 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; @@ -252,7 +190,6 @@ typedef struct glamor_screen_private { glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; Bool glyph_cache_initialized; - struct glamor_gl_dispatch dispatch; } glamor_screen_private; @@ -262,28 +199,6 @@ typedef enum glamor_access { 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. - * #pending_op: currently only support pending filling. - * @container: The corresponding pixmap's pointer. - **/ - -#define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ - (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ - && (pixmap_priv->pending_op.type != GLAMOR_PENDING_NONE)) - -#define GLAMOR_PIXMAP_PRIV_NO_PENDING(pixmap_priv) \ - (pixmap_priv->pending_op.type == GLAMOR_PENDING_NONE) - enum _glamor_pending_op_type{ GLAMOR_PENDING_NONE, GLAMOR_PENDING_FILL @@ -300,6 +215,20 @@ typedef union _glamor_pending_op { glamor_pending_fill fill; } glamor_pending_op; +/* + * 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. + * #pending_op: currently only support pending filling. + * @container: The corresponding pixmap's pointer. + **/ typedef struct glamor_pixmap_private { unsigned char gl_fbo:1; @@ -316,15 +245,6 @@ typedef struct glamor_pixmap_private { glamor_screen_private *glamor_priv; } glamor_pixmap_private; -#define GLAMOR_CHECK_PENDING_FILL(_dispatch_, _glamor_priv_, _pixmap_priv_) do \ - { \ - if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ - _dispatch_->glUseProgram(_glamor_priv_->solid_prog); \ - _dispatch_->glUniform4fv(_glamor_priv_->solid_color_uniform_location, 1, \ - _pixmap_priv_->pending_op.fill.color4fv); \ - } \ - } while(0) - /* * Pixmap dynamic status, used by dynamic upload feature. * @@ -356,347 +276,6 @@ glamor_get_pixmap_private(PixmapPtr pixmap) 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. - * no_alpha is used to indicate whehter we need to wire alpha to 1. - * - * Return 0 if find a matched texture type. Otherwise return -1. - **/ -#ifndef GLAMOR_GLES2 -static inline int -glamor_get_tex_format_type_from_pictformat(PictFormatShort format, - GLenum *tex_format, - GLenum *tex_type, - int *no_alpha, - int *no_revert) -{ - *no_alpha = 0; - *no_revert = 1; - switch (format) { - case PICT_a1: - *tex_format = GL_COLOR_INDEX; - *tex_type = GL_BITMAP; - break; - case PICT_b8g8r8x8: - *no_alpha = 1; - case PICT_b8g8r8a8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8; - break; - - case PICT_x8r8g8b8: - *no_alpha = 1; - case PICT_a8r8g8b8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case PICT_x8b8g8r8: - *no_alpha = 1; - case PICT_a8b8g8r8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case PICT_x2r10g10b10: - *no_alpha = 1; - case PICT_a2r10g10b10: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; - break; - case PICT_x2b10g10r10: - *no_alpha = 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: - *no_alpha = 1; - case PICT_a1b5g5r5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - - case PICT_x1r5g5b5: - *no_alpha = 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: - *no_alpha = 1; - case PICT_a4r4g4b4: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - break; - - case PICT_x4b4g4r4: - *no_alpha = 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; -} -#else -#define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) - -static inline int -glamor_get_tex_format_type_from_pictformat(PictFormatShort format, - GLenum *tex_format, - GLenum *tex_type, - int *no_alpha, - int *no_revert) -{ - *no_alpha = 0; - *no_revert = IS_LITTLE_ENDIAN; - - switch (format) { - case PICT_b8g8r8x8: - *no_alpha = 1; - case PICT_b8g8r8a8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_BYTE; - *no_revert = !IS_LITTLE_ENDIAN; - break; - - case PICT_x8r8g8b8: - *no_alpha = 1; - case PICT_a8r8g8b8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_BYTE; - break; - - case PICT_x8b8g8r8: - *no_alpha = 1; - case PICT_a8b8g8r8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_BYTE; - break; - - case PICT_x2r10g10b10: - *no_alpha = 1; - case PICT_a2r10g10b10: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *no_revert = TRUE; - break; - - case PICT_x2b10g10r10: - *no_alpha = 1; - case PICT_a2b10g10r10: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *no_revert = TRUE; - break; - - case PICT_r5g6b5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *no_revert = TRUE; - break; - - case PICT_b5g6r5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *no_revert = FALSE; - break; - - case PICT_x1b5g5r5: - *no_alpha = 1; - case PICT_a1b5g5r5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *no_revert = TRUE; - break; - - case PICT_x1r5g5b5: - *no_alpha = 1; - case PICT_a1r5g5b5: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *no_revert = TRUE; - break; - - case PICT_a8: - *tex_format = GL_ALPHA; - *tex_type = GL_UNSIGNED_BYTE; - *no_revert = TRUE; - break; - - case PICT_x4r4g4b4: - *no_alpha = 1; - case PICT_a4r4g4b4: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - *no_revert = TRUE; - break; - - case PICT_x4b4g4r4: - *no_alpha = 1; - case PICT_a4b4g4r4: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - *no_revert = TRUE; - break; - - default: - LogMessageVerb(X_INFO, 0, "fail to get matched format for %x \n", format); - return -1; - } - return 0; -} - - -#endif - - -static inline int -glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, - GLenum *format, - GLenum *type, - int *no_alpha, - int *no_revert) -{ - 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, - no_alpha, no_revert); -} - - -/* 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 @@ -775,10 +354,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, void glamor_set_alu(struct glamor_gl_dispatch * dispatch, unsigned char alu); Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); -void glamor_get_transform_uniform_locations(GLint prog, - glamor_transform_uniforms *uniform_locations); -void glamor_set_transform_for_pixmap(PixmapPtr pixmap, - glamor_transform_uniforms *uniform_locations); Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); Bool glamor_gl_has_extension(char *extension); @@ -977,6 +552,8 @@ glamor_upload_picture_to_texture(PicturePtr picture); void glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_priv); +#include"glamor_utils.h" + /* 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, @@ -984,11 +561,9 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr * fallback the whole process to cpu. Most of the time, * this will increase performance obviously. */ - #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #define GLAMOR_DELAYED_FILLING -#include"glamor_utils.h" #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 30432cf1f..fe5bd4e1e 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -159,4 +159,384 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) boxes[i].y2 += dy; } } + +#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)) + +#define glamor_check_fbo_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \ + && (_w_) < _glamor_->max_fbo_size \ + && (_h_) < _glamor_->max_fbo_size) + +#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) + +#define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ + (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ + && (pixmap_priv->pending_op.type != GLAMOR_PENDING_NONE)) + +#define GLAMOR_PIXMAP_PRIV_NO_PENDING(pixmap_priv) \ + (pixmap_priv->pending_op.type == GLAMOR_PENDING_NONE) + +#define GLAMOR_CHECK_PENDING_FILL(_dispatch_, _glamor_priv_, _pixmap_priv_) do \ + { \ + if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ + _dispatch_->glUseProgram(_glamor_priv_->solid_prog); \ + _dispatch_->glUniform4fv(_glamor_priv_->solid_color_uniform_location, 1, \ + _pixmap_priv_->pending_op.fill.color4fv); \ + } \ + } while(0) + + +/** + * 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. + * no_alpha is used to indicate whehter we need to wire alpha to 1. + * + * Return 0 if find a matched texture type. Otherwise return -1. + **/ +#ifndef GLAMOR_GLES2 +static inline int +glamor_get_tex_format_type_from_pictformat(PictFormatShort format, + GLenum *tex_format, + GLenum *tex_type, + int *no_alpha, + int *no_revert) +{ + *no_alpha = 0; + *no_revert = 1; + switch (format) { + case PICT_a1: + *tex_format = GL_COLOR_INDEX; + *tex_type = GL_BITMAP; + break; + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8; + break; + + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + case PICT_x2b10g10r10: + *no_alpha = 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: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + + case PICT_x1r5g5b5: + *no_alpha = 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: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + + case PICT_x4b4g4r4: + *no_alpha = 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; +} +#else +#define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) + +static inline int +glamor_get_tex_format_type_from_pictformat(PictFormatShort format, + GLenum *tex_format, + GLenum *tex_type, + int *no_alpha, + int *no_revert) +{ + *no_alpha = 0; + *no_revert = IS_LITTLE_ENDIAN; + + switch (format) { + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_BYTE; + *no_revert = !IS_LITTLE_ENDIAN; + break; + + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_BYTE; + break; + + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + break; + + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_10_10_10_2; + *no_revert = TRUE; + break; + + case PICT_x2b10g10r10: + *no_alpha = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_10_10_10_2; + *no_revert = TRUE; + break; + + case PICT_r5g6b5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *no_revert = TRUE; + break; + + case PICT_b5g6r5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *no_revert = FALSE; + break; + + case PICT_x1b5g5r5: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + *no_revert = TRUE; + break; + + case PICT_x1r5g5b5: + *no_alpha = 1; + case PICT_a1r5g5b5: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + *no_revert = TRUE; + break; + + case PICT_a8: + *tex_format = GL_ALPHA; + *tex_type = GL_UNSIGNED_BYTE; + *no_revert = TRUE; + break; + + case PICT_x4r4g4b4: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + *no_revert = TRUE; + break; + + case PICT_x4b4g4r4: + *no_alpha = 1; + case PICT_a4b4g4r4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + *no_revert = TRUE; + break; + + default: + LogMessageVerb(X_INFO, 0, "fail to get matched format for %x \n", format); + return -1; + } + return 0; +} + + +#endif + + +static inline int +glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, + GLenum *format, + GLenum *type, + int *no_alpha, + int *no_revert) +{ + 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, + no_alpha, no_revert); +} + + +/* 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; +} + + + + + + #endif From 67dbe0ddf87a6dd602d3d4a6049072f6386d757e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 8 Sep 2011 15:16:01 +0800 Subject: [PATCH 210/462] glamor-egl: Added new function to create image for a pixmap. This function is used to support dri2. In the underlying driver, it will create a buffer object for a given pixmap. And then call this api to create a egl image from that buffer object, and then bind that image to a texture, and then bind that texture to the pixmap. Normally, this pixmap's content is shared between a dri2 client and the x server. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 193 ++++++++++++++++++++++++++++---------------- 1 file changed, 125 insertions(+), 68 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 773f90e2e..d95828e55 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -54,7 +54,7 @@ #define GLAMOR_FOR_XORG #include -#include +#include "glamor_gl_dispatch.h" #define GLAMOR_VERSION_MAJOR 0 #define GLAMOR_VERSION_MINOR 1 @@ -68,13 +68,12 @@ glamor_identify(int flags) xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver based.\n", glamor_name); } -struct glamor_screen_private { +struct glamor_egl_screen_private { EGLDisplay display; EGLContext context; EGLImageKHR root; EGLint major, minor; - CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; int fd; @@ -90,19 +89,15 @@ struct glamor_screen_private { int xf86GlamorEGLPrivateIndex = -1; -static struct glamor_screen_private* glamor_get_egl_screen_private(ScrnInfoPtr scrn) +static struct glamor_egl_screen_private* glamor_get_egl_screen_private(ScrnInfoPtr scrn) { - return (struct glamor_screen_private *) scrn->privates[xf86GlamorEGLPrivateIndex].ptr; + return (struct glamor_egl_screen_private *) scrn->privates[xf86GlamorEGLPrivateIndex].ptr; } -static Bool -_glamor_create_egl_screen_image(ScrnInfoPtr scrn, int width, int height, int stride) +static EGLImageKHR +_glamor_create_egl_image(struct glamor_egl_screen_private *glamor_egl, int width, int height, int stride, int name) { - - struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; EGLImageKHR image; - GLuint texture; EGLint attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, @@ -113,64 +108,122 @@ _glamor_create_egl_screen_image(ScrnInfoPtr scrn, int width, int height, int str EGL_NONE }; - if (glamor->root) { - eglDestroyImageKHR(glamor->display, glamor->root); - glamor->root = EGL_NO_IMAGE_KHR; - } - + attribs[1] = width; attribs[3] = height; attribs[5] = stride / 4; - image = glamor->egl_create_image_khr (glamor->display, - glamor->context, - EGL_DRM_BUFFER_MESA, - (void*)glamor->front_buffer_handle, - attribs); + image = glamor_egl->egl_create_image_khr (glamor_egl->display, + glamor_egl->context, + EGL_DRM_BUFFER_MESA, + (void*)name, + attribs); if (image == EGL_NO_IMAGE_KHR) - return FALSE; + return EGL_NO_IMAGE_KHR; - glamor->dispatch->glGenTextures(1, &texture); - glamor->dispatch->glBindTexture(GL_TEXTURE_2D, texture); - glamor->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glamor->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); - - glamor_set_screen_pixmap_texture(screen, width, height, texture); - glamor->root = image; - return TRUE; + return image; } +static int +glamor_get_flink_name(int fd, int handle, int *name) +{ + struct drm_gem_flink flink; + flink.handle = handle; + if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) + return FALSE; + *name = flink.name; + return TRUE; +} + +static Bool +glamor_create_texture_from_image(struct glamor_egl_screen_private *glamor_egl, EGLImageKHR image, GLuint *texture) +{ + glamor_egl->dispatch->glGenTextures(1, texture); + glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, *texture); + glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + (glamor_egl->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); + return TRUE; +} + + Bool glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); - struct drm_gem_flink flink; - flink.handle = handle; + struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + EGLImageKHR image; + GLuint texture; - if (ioctl(glamor->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, + if (!glamor_get_flink_name(glamor_egl->fd, handle, &glamor_egl->front_buffer_handle)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink front buffer handle\n"); - return FALSE; + return FALSE; } - glamor->front_buffer_handle = flink.name; + if (glamor_egl->root) { + eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); + glamor_egl->root = EGL_NO_IMAGE_KHR; + } + + image = _glamor_create_egl_image( glamor_egl, + scrn->virtualX, + scrn->virtualY, + stride, + glamor_egl->front_buffer_handle); + if (image == EGL_NO_IMAGE_KHR) + return FALSE; + + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_screen_pixmap_texture(screen, scrn->virtualX, scrn->virtualY, texture); + glamor_egl->root = image; + return TRUE; +} - return _glamor_create_egl_screen_image(scrn, scrn->virtualX, scrn->virtualY, stride); +/* + * This function will be called from the dri buffer allocation. + * It is somehow very familiar with the create screen image. + */ +Bool +glamor_create_egl_pixmap_image(PixmapPtr pixmap, int handle, int stride) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + EGLImageKHR image; + GLuint texture; + int name; + if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink pixmap handle\n"); + return FALSE; + } + + image = _glamor_create_egl_image( glamor_egl, + pixmap->drawable.width, + pixmap->drawable.height, + stride, + name); + if (image == EGL_NO_IMAGE_KHR) + return FALSE; + + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, pixmap->drawable.height, texture); + return TRUE; } Bool glamor_close_egl_screen(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); glamor_fini(screen); - eglDestroyImageKHR(glamor->display, glamor->root); + eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); - glamor->root = EGL_NO_IMAGE_KHR; + glamor_egl->root = EGL_NO_IMAGE_KHR; return TRUE; } @@ -178,14 +231,14 @@ glamor_close_egl_screen(ScreenPtr screen) static Bool -glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) +glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, char *extension) { const char *egl_extensions; char *pext; int ext_len; ext_len = strlen(extension); - egl_extensions = (const char*)eglQueryString(glamor->display, EGL_EXTENSIONS); + egl_extensions = (const char*)eglQueryString(glamor_egl->display, EGL_EXTENSIONS); pext = (char*)egl_extensions; if (pext == NULL || extension == NULL) @@ -201,7 +254,7 @@ glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) { - struct glamor_screen_private *glamor; + struct glamor_egl_screen_private *glamor_egl; const char *version; EGLint config_attribs[] = { #ifdef GLAMOR_GLES2 @@ -211,30 +264,30 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) }; glamor_identify(0); - glamor = calloc(sizeof(*glamor), 1); + glamor_egl = calloc(sizeof(*glamor_egl), 1); if (xf86GlamorEGLPrivateIndex == -1) xf86GlamorEGLPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor; + scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; - glamor->fd = fd; - glamor->display = eglGetDRMDisplayMESA(glamor->fd); + glamor_egl->fd = fd; + glamor_egl->display = eglGetDRMDisplayMESA(glamor_egl->fd); #ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); #else eglBindAPI(EGL_OPENGL_ES_API); #endif - if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { + if (!eglInitialize(glamor_egl->display, &glamor_egl->major, &glamor_egl->minor)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); return FALSE; } - version = eglQueryString(glamor->display, EGL_VERSION); + version = eglQueryString(glamor_egl->display, EGL_VERSION); xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ - if (!glamor_egl_has_extension(glamor, "EGL_" #EXT)) { \ + if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT)) { \ ErrorF("EGL_" #EXT "required.\n"); \ return FALSE; \ } @@ -247,37 +300,39 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); #endif - glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA) + glamor_egl->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress("eglExportDRMImageMESA"); - glamor->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) + glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); - glamor->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) + glamor_egl->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); - if (!glamor->egl_create_image_khr - || !glamor->egl_export_drm_image_mesa - || !glamor->egl_image_target_texture2d_oes) { + if (!glamor_egl->egl_create_image_khr + || !glamor_egl->egl_export_drm_image_mesa + || !glamor_egl->egl_image_target_texture2d_oes) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetProcAddress() failed\n"); return FALSE; } - glamor->context = eglCreateContext(glamor->display, + glamor_egl->context = eglCreateContext(glamor_egl->display, NULL, EGL_NO_CONTEXT, config_attribs); - if (glamor->context == EGL_NO_CONTEXT) { + if (glamor_egl->context == EGL_NO_CONTEXT) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n"); return FALSE; } - if (!eglMakeCurrent(glamor->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, glamor->context)) { + if (!eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to make EGL context current\n"); return FALSE; } + + return TRUE; } @@ -285,25 +340,27 @@ void glamor_free_egl_screen(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_screen_private *glamor = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); - if (glamor != NULL) + if (glamor_egl != NULL) { if (!(flags & GLAMOR_EGL_EXTERNAL_BUFFER)) { - eglMakeCurrent(glamor->display, + eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate(glamor->display); + eglTerminate(glamor_egl->display); } - free(glamor); + free(glamor_egl); } } +/* egl version. */ + Bool glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, eglGetProcAddress)) return FALSE; glamor_egl->dispatch = dispatch; From 82a9b0c540dcf1064f5184c36a05d6216fb11034 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 16 Sep 2011 13:37:13 +0800 Subject: [PATCH 211/462] glamor-ddx: Change naming of glamor ddx module. Use glamor_ddx prefix for all standalone glamor ddx functions. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor.c | 110 ++++++++++++++++---------------- hw/xfree86/glamor/glamor_crtc.c | 2 +- hw/xfree86/glamor/glamor_ddx.h | 8 +-- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 90357d201..eef8eeb4f 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -49,19 +49,19 @@ #define GLAMOR_VERSION_MINOR 1 #define GLAMOR_VERSION_PATCH 0 -static const char glamor_name[] = "glamor"; +static const char glamor_ddx_name[] = "glamor"; static void -glamor_identify(int flags) +glamor_ddx_identify(int flags) { - xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver\n", glamor_name); + xf86Msg(X_INFO, "Standalone %s: OpenGL accelerated X.org driver\n", glamor_ddx_name); } Bool glamor_resize(ScrnInfoPtr scrn, int width, int height) { - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; EGLImageKHR image; GLuint texture; @@ -100,14 +100,14 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) void glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) { - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); EGLint name; (glamor->egl_export_drm_image_mesa)(glamor->display, glamor->root, &name, (EGLint*) handle, (EGLint*) pitch); } EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) { - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); EGLint attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, @@ -124,14 +124,14 @@ EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor) { - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); eglDestroyImageKHR(glamor->display, cursor); } void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uint32_t *pitch) { - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); EGLint name; (glamor->egl_export_drm_image_mesa)(glamor->display, cursor, &name, (EGLint*) handle, (EGLint*) pitch); ErrorF("cursor stride: %d\n", *pitch); @@ -139,9 +139,9 @@ glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uin char * dri_device_name = "/dev/dri/card0"; static Bool -glamor_pre_init_ddx(ScrnInfoPtr scrn, int flags) +glamor_ddx_pre_init(ScrnInfoPtr scrn, int flags) { - struct glamor_screen_private *glamor; + struct glamor_ddx_screen_private *glamor; rgb defaultWeight = { 0, 0, 0 }; glamor = xnfcalloc(sizeof *glamor, 1); @@ -193,15 +193,15 @@ fail: } static void -glamor_adjust_frame_ddx(int scrnIndex, int x, int y, int flags) +glamor_ddx_adjust_frame(int scrnIndex, int x, int y, int flags) { } static Bool -glamor_enter_vt_ddx(int scrnIndex, int flags) +glamor_ddx_enter_vt(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); if (drmSetMaster(glamor->fd)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -216,19 +216,19 @@ glamor_enter_vt_ddx(int scrnIndex, int flags) } static void -glamor_leave_vt_ddx(int scrnIndex, int flags) +glamor_ddx_leave_vt(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); drmDropMaster(glamor->fd); } static Bool -glamor_create_screen_resources_ddx(ScreenPtr screen) +glamor_ddx_create_screen_resources(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); screen->CreateScreenResources = glamor->CreateScreenResources; if (!(*screen->CreateScreenResources) (screen)) @@ -243,16 +243,16 @@ glamor_create_screen_resources_ddx(ScreenPtr screen) } static Bool -glamor_close_screen_ddx(int scrnIndex, ScreenPtr screen) +glamor_ddx_close_screen(int scrnIndex, ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); screen->CloseScreen = glamor->CloseScreen; (*screen->CloseScreen) (scrnIndex, screen); if (scrn->vtSema == TRUE) - glamor_leave_vt_ddx(scrnIndex, 0); + glamor_ddx_leave_vt(scrnIndex, 0); glamor_fini(screen); @@ -274,7 +274,7 @@ glamor_close_screen_ddx(int scrnIndex, ScreenPtr screen) static Bool -glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) +glamor_egl_has_extension(struct glamor_ddx_screen_private *glamor, char *extension) { const char *egl_extensions; char *pext; @@ -297,10 +297,10 @@ glamor_egl_has_extension(struct glamor_screen_private *glamor, char *extension) static Bool -glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) +glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); const char *version; VisualPtr visual; EGLint config_attribs[] = { @@ -343,7 +343,7 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) } version = eglQueryString(glamor->display, EGL_VERSION); - xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); + xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_ddx_name, version); #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ if (!glamor_egl_has_extension(glamor, "EGL_" #EXT)) { \ @@ -446,14 +446,14 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) * later memory should be bound when allocating, e.g rotate_mem */ scrn->vtSema = TRUE; - if (!glamor_enter_vt_ddx(scrnIndex, 0)) + if (!glamor_ddx_enter_vt(scrnIndex, 0)) return FALSE; screen->SaveScreen = xf86SaveScreen; glamor->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = glamor_create_screen_resources_ddx; + screen->CreateScreenResources = glamor_ddx_create_screen_resources; glamor->CloseScreen = screen->CloseScreen; - screen->CloseScreen = glamor_close_screen_ddx; + screen->CloseScreen = glamor_ddx_close_screen; /* Fixme should we init crtc screen here? */ if (!xf86CrtcScreenInit(screen)) return FALSE; @@ -467,10 +467,10 @@ glamor_screen_init_ddx(int scrnIndex, ScreenPtr screen, int argc, char **argv) } static void -glamor_free_screen_ddx(int scrnIndex, int flags) +glamor_ddx_free_screen(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); if (glamor != NULL) { close(glamor->fd); @@ -480,7 +480,7 @@ glamor_free_screen_ddx(int scrnIndex, int flags) } static ModeStatus -glamor_valid_mode_ddx(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +glamor_ddx_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { if (mode->Flags & V_INTERLACE) { if (verbose) { @@ -494,13 +494,13 @@ glamor_valid_mode_ddx(int scrnIndex, DisplayModePtr mode, Bool verbose, int flag } static Bool -glamor_probe(struct _DriverRec *drv, int flags) +glamor_ddx_probe(struct _DriverRec *drv, int flags) { ScrnInfoPtr scrn = NULL; GDevPtr *sections; int entity, n; - n = xf86MatchDevice(glamor_name, §ions); + n = xf86MatchDevice(glamor_ddx_name, §ions); if (n <= 0) return FALSE; @@ -513,29 +513,29 @@ glamor_probe(struct _DriverRec *drv, int flags) } scrn->driverVersion = 1; - scrn->driverName = (char *) glamor_name; - scrn->name = (char *) glamor_name; + scrn->driverName = (char *) glamor_ddx_name; + scrn->name = (char *) glamor_ddx_name; scrn->Probe = NULL; - scrn->PreInit = glamor_pre_init_ddx; - scrn->ScreenInit = glamor_screen_init_ddx; - scrn->AdjustFrame = glamor_adjust_frame_ddx; - scrn->EnterVT = glamor_enter_vt_ddx; - scrn->LeaveVT = glamor_leave_vt_ddx; - scrn->FreeScreen = glamor_free_screen_ddx; - scrn->ValidMode = glamor_valid_mode_ddx; + scrn->PreInit = glamor_ddx_pre_init; + scrn->ScreenInit = glamor_ddx_screen_init; + scrn->AdjustFrame = glamor_ddx_adjust_frame; + scrn->EnterVT = glamor_ddx_enter_vt; + scrn->LeaveVT = glamor_ddx_leave_vt; + scrn->FreeScreen = glamor_ddx_free_screen; + scrn->ValidMode = glamor_ddx_valid_mode; return TRUE; } static const OptionInfoRec * -glamor_available_options(int chipid, int busid) +glamor_ddx_available_options(int chipid, int busid) { return NULL; } static Bool -glamor_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) +glamor_ddx_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) { xorgHWFlags *flag; @@ -550,19 +550,19 @@ glamor_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) } } -_X_EXPORT DriverRec glamor = { +_X_EXPORT DriverRec glamor_ddx = { 1, "glamor", - glamor_identify, - glamor_probe, - glamor_available_options, + glamor_ddx_identify, + glamor_ddx_probe, + glamor_ddx_available_options, NULL, 0, - glamor_driver_func, + glamor_ddx_driver_func, }; static pointer -glamor_setup(pointer module, pointer opts, int *errmaj, int *errmin) +glamor_ddx_setup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = 0; @@ -570,7 +570,7 @@ glamor_setup(pointer module, pointer opts, int *errmaj, int *errmin) */ if (!setupDone) { setupDone = 1; - xf86AddDriver(&glamor, module, HaveDriverFuncs); + xf86AddDriver(&glamor_ddx, module, HaveDriverFuncs); /* * The return value must be non-NULL on success even though there @@ -588,7 +588,7 @@ Bool glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_screen_private *glamor_egl = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor_egl = glamor_ddx_get_screen_private(scrn); if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, eglGetProcAddress)) return FALSE; glamor_egl->dispatch = dispatch; @@ -596,8 +596,8 @@ glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, i } -static XF86ModuleVersionInfo glamor_version_info = { - glamor_name, +static XF86ModuleVersionInfo glamor_ddx_version_info = { + glamor_ddx_name, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, @@ -612,7 +612,7 @@ static XF86ModuleVersionInfo glamor_version_info = { }; _X_EXPORT XF86ModuleData glamorModuleData = { - &glamor_version_info, - glamor_setup, + &glamor_ddx_version_info, + glamor_ddx_setup, NULL }; diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index ef6ee2946..60af8b544 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -478,7 +478,7 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ScrnInfoPtr scrn = crtc->scrn; - struct glamor_screen_private *glamor = glamor_get_screen_private(scrn); + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); if (drmmode_crtc->cursor == NULL) { diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index 2c14ca18e..e083864ad 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -17,7 +17,7 @@ #include #include "glamor_gl_dispatch.h" -struct glamor_screen_private { +struct glamor_ddx_screen_private { EGLDisplay display; EGLContext context; EGLImageKHR root; @@ -34,10 +34,10 @@ struct glamor_screen_private { struct glamor_gl_dispatch *dispatch; }; -inline struct glamor_screen_private * -glamor_get_screen_private(ScrnInfoPtr scrn) +inline struct glamor_ddx_screen_private * +glamor_ddx_get_screen_private(ScrnInfoPtr scrn) { - return (struct glamor_screen_private *) (scrn->driverPrivate); + return (struct glamor_ddx_screen_private *) (scrn->driverPrivate); } Bool glamor_resize(ScrnInfoPtr scrn, int width, int height); From 4c8ed1756aa5121a559aa604926a730180a1403f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 19 Sep 2011 06:31:57 +0800 Subject: [PATCH 212/462] glamor-ddx: Use gbm to allocate front buffer and cursor image. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor.c | 67 ++++++++++++++++++---------------- hw/xfree86/glamor/glamor_ddx.h | 8 +++- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index eef8eeb4f..a51593994 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -30,12 +30,14 @@ #ifdef HAVE_DIX_CONFIG_H #include #endif + +#include + #include #include #include #include - #include "../../../mi/micmap.h" #include #include @@ -57,7 +59,6 @@ glamor_ddx_identify(int flags) xf86Msg(X_INFO, "Standalone %s: OpenGL accelerated X.org driver\n", glamor_ddx_name); } - Bool glamor_resize(ScrnInfoPtr scrn, int width, int height) { @@ -65,25 +66,25 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; EGLImageKHR image; GLuint texture; - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA | - EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; if (glamor->root != EGL_NO_IMAGE_KHR && scrn->virtualX == width && scrn->virtualY == height) return TRUE; - attribs[1] = width; - attribs[3] = height; - image = (glamor->egl_create_drm_image_mesa)(glamor->display, attribs); - if (image == EGL_NO_IMAGE_KHR) + glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, + GBM_BO_FORMAT_ARGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + + if (glamor->root_bo == NULL) return FALSE; + image = glamor->egl_create_image_khr(glamor->display, NULL, EGL_NATIVE_PIXMAP_KHR, glamor->root_bo, NULL); + + if (image == EGL_NO_IMAGE_KHR) { + gbm_bo_destroy(glamor->root_bo); + return FALSE; + } + glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -101,39 +102,36 @@ void glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) { struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - EGLint name; - (glamor->egl_export_drm_image_mesa)(glamor->display, glamor->root, &name, (EGLint*) handle, (EGLint*) pitch); + *handle = gbm_bo_get_handle(glamor->root_bo).u32; + *pitch = gbm_bo_get_pitch(glamor->root_bo); } EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) { struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA | - EGL_DRM_BUFFER_USE_SCANOUT_MESA | EGL_DRM_BUFFER_USE_CURSOR_MESA, - EGL_NONE - }; + glamor->cursor_bo = gbm_bo_create(glamor->gbm, width, height, + GBM_BO_FORMAT_ARGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_CURSOR_64X64); - attribs[1] = width; - attribs[3] = height; - return (glamor->egl_create_drm_image_mesa)(glamor->display, attribs); + if (glamor->cursor_bo == NULL) + return EGL_NO_IMAGE_KHR; + + return glamor->egl_create_image_khr(glamor->display, NULL, EGL_NATIVE_PIXMAP_KHR, glamor->cursor_bo, NULL); } void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor) { struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); eglDestroyImageKHR(glamor->display, cursor); + gbm_bo_destroy(glamor->cursor_bo); } void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uint32_t *pitch) { struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - EGLint name; - (glamor->egl_export_drm_image_mesa)(glamor->display, cursor, &name, (EGLint*) handle, (EGLint*) pitch); + *handle = gbm_bo_get_handle(glamor->cursor_bo).u32; + *pitch = gbm_bo_get_pitch(glamor->cursor_bo); ErrorF("cursor stride: %d\n", *pitch); } @@ -257,6 +255,7 @@ glamor_ddx_close_screen(int scrnIndex, ScreenPtr screen) glamor_fini(screen); eglDestroyImageKHR(glamor->display, glamor->root); + gbm_bo_destroy(glamor->root_bo); eglMakeCurrent(glamor->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); @@ -328,9 +327,13 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) } + glamor->gbm = gbm_create_device(glamor->fd); + if (glamor->gbm == NULL) { + ErrorF("couldn't create gbm device\n"); + return FALSE; + } - - glamor->display = eglGetDRMDisplayMESA(glamor->fd); + glamor->display = eglGetDisplay(glamor->gbm); #ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); #else @@ -360,6 +363,8 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) #endif glamor->egl_create_drm_image_mesa = (PFNEGLCREATEDRMIMAGEMESA)eglGetProcAddress("eglCreateDRMImageMESA"); + glamor->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) + eglGetProcAddress("eglCreateImageKHR"); glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA)eglGetProcAddress("eglExportDRMImageMESA"); glamor->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index e083864ad..bed7bb921 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -16,25 +16,31 @@ #include #include +#include #include "glamor_gl_dispatch.h" struct glamor_ddx_screen_private { EGLDisplay display; EGLContext context; EGLImageKHR root; + struct gbm_bo *root_bo; + struct gbm_bo *cursor_bo; + EGLint major, minor; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; int fd; int cpp; + struct gbm_device *gbm; PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; + PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; struct glamor_gl_dispatch *dispatch; }; -inline struct glamor_ddx_screen_private * +inline static struct glamor_ddx_screen_private * glamor_ddx_get_screen_private(ScrnInfoPtr scrn) { return (struct glamor_ddx_screen_private *) (scrn->driverPrivate); From 2d4d40a4b5938249f3c73ed14fe5c5b926c2fefd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 19 Sep 2011 09:45:32 +0800 Subject: [PATCH 213/462] glamor-ddx: Fix the broken switching between VTs. Now we can allocate frame buffer during the screen initialization. And set mode major when enter VT. This is the correct logic. The previous implementation defer the set mode major to create screen resource which will cause the switching between VTs broken. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor.c | 42 ++++++++++++++++++++++++++------- hw/xfree86/glamor/glamor_crtc.c | 16 +++++++++++-- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index a51593994..1bb5835db 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -70,11 +70,18 @@ glamor_resize(ScrnInfoPtr scrn, int width, int height) if (glamor->root != EGL_NO_IMAGE_KHR && scrn->virtualX == width && scrn->virtualY == height) return TRUE; + else if (scrn->virtualX != width || scrn->virtualY != height) { - glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, + if (glamor->root != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(glamor->display, glamor->root); + gbm_bo_destroy(glamor->root_bo); + glamor->root = EGL_NO_IMAGE_KHR; + } + glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, GBM_BO_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - + } + if (glamor->root_bo == NULL) return FALSE; @@ -206,10 +213,8 @@ glamor_ddx_enter_vt(int scrnIndex, int flags) "drmSetMaster failed: %s\n", strerror(errno)); return FALSE; } -#if 0 if (!xf86SetDesiredModes(scrn)) return FALSE; -#endif return TRUE; } @@ -227,15 +232,15 @@ glamor_ddx_create_screen_resources(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); + int width = scrn->virtualX; + int height = scrn->virtualY; screen->CreateScreenResources = glamor->CreateScreenResources; if (!(*screen->CreateScreenResources) (screen)) return FALSE; if (!glamor_glyphs_init(screen)) return FALSE; - - if (!xf86SetDesiredModes(scrn)) - return FALSE; + glamor_resize(scrn, width, height); return TRUE; } @@ -293,7 +298,23 @@ glamor_egl_has_extension(struct glamor_ddx_screen_private *glamor, char *extensi return FALSE; } +static Bool +glamor_ddx_init_front_buffer(ScrnInfoPtr scrn) +{ + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); + int width = scrn->virtualX; + int height = scrn->virtualY; + glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, + GBM_BO_FORMAT_ARGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + + if (glamor->root_bo == NULL) + return FALSE; + + /* XXX shall we update displayWidth here ? */ + return TRUE; +} static Bool glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) @@ -304,10 +325,10 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) VisualPtr visual; EGLint config_attribs[] = { #ifdef GLAMOR_GLES2 - EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_CONTEXT_CLIENT_VERSION, 2, #endif EGL_NONE - }; + }; /* If serverGeneration != 1 then fd was closed during the last @@ -398,6 +419,9 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) if (!miSetPixmapDepths()) return FALSE; + if (!glamor_ddx_init_front_buffer(scrn)) + return FALSE; + if (!fbScreenInit(screen, NULL, scrn->virtualX, scrn->virtualY, scrn->xDpi, scrn->yDpi, diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 60af8b544..4cb378058 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -372,10 +372,22 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, int ret = TRUE; int i; int fb_id; + uint32_t handle, pitch; drmModeModeInfo kmode; - if (!drmmode_update_fb(scrn, scrn->virtualX, scrn->virtualY)) - return FALSE; + if (drmmode->fb_id == 0) { + + glamor_frontbuffer_handle(scrn, &handle, &pitch); + ret = drmModeAddFB(drmmode->fd, + scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, + pitch, handle, + &drmmode->fb_id); + if (ret < 0) { + ErrorF("failed to add fb\n"); + return FALSE; + } + } saved_mode = crtc->mode; saved_x = crtc->x; From 1590da001129ea61d6f7f8758d1d2842825be81b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 20 Sep 2011 15:14:49 +0800 Subject: [PATCH 214/462] glamor-egl: Add gbm device support. Latest mesa EGL implementation move to use gbm to manage/allocate buffers. To keep backward compatibility, we still try to use eglGetDRMDisplayMESA firstly, and if failed, then turn to use eglGetDisplay(gbm). Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index d95828e55..921023eae 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -40,6 +40,8 @@ #define EGL_EGLEXT_PROTOTYPES #define EGL_DISPLAY_NO_X_MESA +#include + #if GLAMOR_GLES2 #include #include @@ -79,6 +81,7 @@ struct glamor_egl_screen_private { int fd; int front_buffer_handle; int cpp; + struct gbm_device *gbm; PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; @@ -184,6 +187,8 @@ glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride) /* * This function will be called from the dri buffer allocation. * It is somehow very familiar with the create screen image. + * XXX the egl image here is not stored at any data structure. + * Does this cause a leak problem? */ Bool glamor_create_egl_pixmap_image(PixmapPtr pixmap, int handle, int stride) @@ -271,7 +276,18 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; glamor_egl->fd = fd; - glamor_egl->display = eglGetDRMDisplayMESA(glamor_egl->fd); + + glamor_egl->display = eglGetDRMDisplayMESA(glamor_egl->fd); + + if (glamor_egl->display == EGL_NO_DISPLAY) { + glamor_egl->gbm = gbm_create_device(glamor_egl->fd); + if (glamor_egl->gbm == NULL) { + ErrorF("couldn't get display device\n"); + return FALSE; + } + } + + glamor_egl->display = eglGetDisplay(glamor_egl->gbm); #ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); #else From 09c63d320112fbb4995696d813c488e82915c2f5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 20 Sep 2011 15:19:13 +0800 Subject: [PATCH 215/462] glamor-ddx: Reuse glamor_dix module to handle egl platform. We already have a glamor egl module at glamor directory which could initialize and create egl context and also can attach a gbm buffer to a specified pixmap or to the screen pixmap. This commit remove all the duplicated code here and use the glamor_dix module directly. As we don't want to handle egl stuffs in this layer, we have to change the way to handle hardware cursor. Previous method is to call egl functions to create a egl image and then bind the image to a texutre then call gl functions to load texture image to the cursor bo. Now we can bind the cursor bo to a cursor pixmap and then use putimage to load new image to the cursor bo. Then we can completely avoid to call egl or gl functions directly in this ddx driver. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/Makefile.am | 3 +- hw/xfree86/glamor/glamor.c | 263 ++++++++++---------------------- hw/xfree86/glamor/glamor_crtc.c | 72 +++------ hw/xfree86/glamor/glamor_ddx.h | 44 ++---- 4 files changed, 121 insertions(+), 261 deletions(-) diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index 8432645ca..fbd561cd1 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -9,14 +9,13 @@ glamor_la_CFLAGS = \ -I$(top_srcdir)/hw/xfree86/ddc \ -I$(top_srcdir)/hw/xfree86/ramdac \ -I$(top_srcdir)/hw/xfree86/i2c \ - -I$(top_srcdir)/glamor + -I$(top_srcdir)/glamor if GLAMOR_GLES2 glamor_la_CFLAGS+=-DGLAMOR_GLES2 endif glamor_la_LDFLAGS = -module -avoid-version \ - $(top_builddir)/glamor/libglamor.la \ $(EGL_LIBS) glamor_ladir = $(moduledir)/drivers diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 1bb5835db..0dbee1806 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -41,9 +41,9 @@ #include "../../../mi/micmap.h" #include #include -#define GC XORG_GC +//#define GC XORG_GC #include -#undef GC +//#undef GC #include "glamor_ddx.h" @@ -59,50 +59,50 @@ glamor_ddx_identify(int flags) xf86Msg(X_INFO, "Standalone %s: OpenGL accelerated X.org driver\n", glamor_ddx_name); } -Bool -glamor_resize(ScrnInfoPtr scrn, int width, int height) +static Bool +glamor_ddx_init_front_buffer(ScrnInfoPtr scrn, int width, int height) { struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - EGLImageKHR image; - GLuint texture; - if (glamor->root != EGL_NO_IMAGE_KHR && - scrn->virtualX == width && scrn->virtualY == height) - return TRUE; - else if (scrn->virtualX != width || scrn->virtualY != height) { - - if (glamor->root != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(glamor->display, glamor->root); - gbm_bo_destroy(glamor->root_bo); - glamor->root = EGL_NO_IMAGE_KHR; - } - glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, + glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, GBM_BO_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - } - + if (glamor->root_bo == NULL) return FALSE; - image = glamor->egl_create_image_khr(glamor->display, NULL, EGL_NATIVE_PIXMAP_KHR, glamor->root_bo, NULL); + scrn->virtualX = width; + scrn->virtualY = height; + /* XXX shall we update displayWidth here ? */ + return TRUE; +} - if (image == EGL_NO_IMAGE_KHR) { - gbm_bo_destroy(glamor->root_bo); - return FALSE; - } +static Bool +glamor_create_screen_image(ScrnInfoPtr scrn) +{ + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; + unsigned int handle, stride; + handle = gbm_bo_get_handle(glamor->root_bo).u32; + stride = gbm_bo_get_pitch(glamor->root_bo); + return glamor_create_egl_screen_image(screen, handle, stride); +} - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); +Bool +glamor_front_buffer_resize(ScrnInfoPtr scrn, int width, int height) +{ + struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - glamor_set_screen_pixmap_texture(screen, width, height, texture); - glamor->root = image; - scrn->virtualX = width; - scrn->virtualY = height; - return TRUE; + if (glamor->root_bo != NULL) { + glamor_close_egl_screen(screen); + gbm_bo_destroy(glamor->root_bo); + glamor->root_bo = NULL; + } + + if (!glamor_ddx_init_front_buffer(scrn, width, height)) + return FALSE; + return glamor_create_screen_image(scrn); } void @@ -113,32 +113,56 @@ glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) *pitch = gbm_bo_get_pitch(glamor->root_bo); } -EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height) +Bool +glamor_create_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor, int width, int height) { struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - glamor->cursor_bo = gbm_bo_create(glamor->gbm, width, height, + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; + unsigned int handle, stride; + + + if (cursor->cursor_pixmap) + glamor_destroy_cursor(scrn, cursor); + + cursor->cursor_pixmap = screen->CreatePixmap(screen, 0, 0, 32, 0); + if (cursor->cursor_pixmap == NULL) + return FALSE; + screen->ModifyPixmapHeader(cursor->cursor_pixmap, width, height, 0, 0, 0, 0); + cursor->cursor_bo = gbm_bo_create(glamor->gbm, width, height, GBM_BO_FORMAT_ARGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_CURSOR_64X64); + GBM_BO_USE_SCANOUT + | GBM_BO_USE_RENDERING + | GBM_BO_USE_CURSOR_64X64); - if (glamor->cursor_bo == NULL) - return EGL_NO_IMAGE_KHR; + if (cursor->cursor_bo == NULL) + goto fail; + glamor_cursor_handle(cursor, &handle, &stride); + if (!glamor_create_egl_pixmap_image(cursor->cursor_pixmap, handle, stride)) + goto fail; - return glamor->egl_create_image_khr(glamor->display, NULL, EGL_NATIVE_PIXMAP_KHR, glamor->cursor_bo, NULL); + return TRUE; + +fail: + glamor_destroy_cursor(scrn, cursor); + return FALSE; } -void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor) +void glamor_destroy_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor) { - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - eglDestroyImageKHR(glamor->display, cursor); - gbm_bo_destroy(glamor->cursor_bo); + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; + if (cursor->cursor_pixmap) + screen->DestroyPixmap(cursor->cursor_pixmap); + if (cursor->cursor_bo) + gbm_bo_destroy(cursor->cursor_bo); + cursor->cursor_bo = NULL; + cursor->cursor_pixmap = NULL; } void -glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR cursor, uint32_t *handle, uint32_t *pitch) +glamor_cursor_handle(struct glamor_gbm_cursor *cursor, uint32_t *handle, uint32_t *pitch) { - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - *handle = gbm_bo_get_handle(glamor->cursor_bo).u32; - *pitch = gbm_bo_get_pitch(glamor->cursor_bo); + *handle = gbm_bo_get_handle(cursor->cursor_bo).u32; + *pitch = gbm_bo_get_pitch(cursor->cursor_bo); ErrorF("cursor stride: %d\n", *pitch); } @@ -189,6 +213,9 @@ glamor_ddx_pre_init(ScrnInfoPtr scrn, int flags) if (!xf86LoadSubModule(scrn, "fb")) goto fail; + if (!xf86LoadSubModule(scrn, "glamor_dix")) + goto fail; + return TRUE; fail: @@ -232,16 +259,16 @@ glamor_ddx_create_screen_resources(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - int width = scrn->virtualX; - int height = scrn->virtualY; screen->CreateScreenResources = glamor->CreateScreenResources; if (!(*screen->CreateScreenResources) (screen)) return FALSE; if (!glamor_glyphs_init(screen)) return FALSE; - glamor_resize(scrn, width, height); - + if (glamor->root_bo == NULL) + return FALSE; + if (!glamor_create_screen_image(scrn)) + return FALSE; return TRUE; } @@ -258,79 +285,22 @@ glamor_ddx_close_screen(int scrnIndex, ScreenPtr screen) glamor_ddx_leave_vt(scrnIndex, 0); glamor_fini(screen); - - eglDestroyImageKHR(glamor->display, glamor->root); + glamor_close_egl_screen(screen); gbm_bo_destroy(glamor->root_bo); - eglMakeCurrent(glamor->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate(glamor->display); - drmmode_closefb(scrn); glamor->fd = -1; - glamor->root = EGL_NO_IMAGE_KHR; - return TRUE; } - - -static Bool -glamor_egl_has_extension(struct glamor_ddx_screen_private *glamor, char *extension) -{ - const char *egl_extensions; - char *pext; - int ext_len; - ext_len = strlen(extension); - - egl_extensions = (const char*)eglQueryString(glamor->display, EGL_EXTENSIONS); - pext = (char*)egl_extensions; - - if (pext == NULL || extension == NULL) - return FALSE; - while((pext = strstr(pext, extension)) != NULL) { - if (pext[ext_len] == ' ' || pext[ext_len] == '\0') - return TRUE; - pext += ext_len; - } - return FALSE; -} - -static Bool -glamor_ddx_init_front_buffer(ScrnInfoPtr scrn) -{ - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - int width = scrn->virtualX; - int height = scrn->virtualY; - - glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, - GBM_BO_FORMAT_ARGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - - if (glamor->root_bo == NULL) - return FALSE; - - /* XXX shall we update displayWidth here ? */ - return TRUE; -} - static Bool glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - const char *version; VisualPtr visual; - EGLint config_attribs[] = { -#ifdef GLAMOR_GLES2 - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - - /* If serverGeneration != 1 then fd was closed during the last time closing screen, actually in eglTerminate(). */ @@ -354,62 +324,7 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) return FALSE; } - glamor->display = eglGetDisplay(glamor->gbm); -#ifndef GLAMOR_GLES2 - eglBindAPI(EGL_OPENGL_API); -#else - eglBindAPI(EGL_OPENGL_ES_API); -#endif - if (!eglInitialize(glamor->display, &glamor->major, &glamor->minor)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "eglInitialize() failed\n"); - return FALSE; - } - - version = eglQueryString(glamor->display, EGL_VERSION); - xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_ddx_name, version); - -#define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ - if (!glamor_egl_has_extension(glamor, "EGL_" #EXT)) { \ - ErrorF("EGL_" #EXT "required.\n"); \ - return FALSE; \ - } - - GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); - GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); -#ifdef GLAMOR_GLES2 - GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_gles2); -#else - GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); -#endif - - glamor->egl_create_drm_image_mesa = (PFNEGLCREATEDRMIMAGEMESA)eglGetProcAddress("eglCreateDRMImageMESA"); - glamor->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) - eglGetProcAddress("eglCreateImageKHR"); - glamor->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA)eglGetProcAddress("eglExportDRMImageMESA"); - glamor->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - - if (!glamor->egl_create_drm_image_mesa || !glamor->egl_export_drm_image_mesa || - !glamor->egl_image_target_texture2d_oes) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "eglGetProcAddress() failed\n"); - return FALSE; - } - - glamor->context = eglCreateContext(glamor->display, - NULL, EGL_NO_CONTEXT, config_attribs); - if (glamor->context == EGL_NO_CONTEXT) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to create EGL context\n"); - return FALSE; - } - - if (!eglMakeCurrent(glamor->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, glamor->context)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to make EGL context current\n"); - return FALSE; - } + glamor_egl_init(scrn, glamor->fd); miClearVisualTypes(); if (!miSetVisualTypes(scrn->depth, @@ -419,7 +334,7 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) if (!miSetPixmapDepths()) return FALSE; - if (!glamor_ddx_init_front_buffer(scrn)) + if (!glamor_ddx_init_front_buffer(scrn, scrn->virtualX, scrn->virtualY)) return FALSE; if (!fbScreenInit(screen, NULL, @@ -613,18 +528,6 @@ glamor_ddx_setup(pointer module, pointer opts, int *errmaj, int *errmin) } } -Bool -glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_ddx_screen_private *glamor_egl = glamor_ddx_get_screen_private(scrn); - if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, eglGetProcAddress)) - return FALSE; - glamor_egl->dispatch = dispatch; - return TRUE; -} - - static XF86ModuleVersionInfo glamor_ddx_version_info = { glamor_ddx_name, MODULEVENDORSTRING, diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 4cb378058..854e81645 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -50,23 +50,6 @@ #include #include -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#define EGL_DISPLAY_NO_X_MESA - -#if GLAMOR_GLES2 -#include -#include -#ifndef GL_BGRA -#define GL_BGRA GL_BGRA_EXT -#endif -#else -#include -#endif - -#include -#include - #include "glamor_ddx.h" typedef struct { @@ -85,8 +68,7 @@ typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; uint32_t rotate_fb_id; - EGLImageKHR cursor; - unsigned int cursor_tex; + struct glamor_gbm_cursor *cursor; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -341,7 +323,7 @@ drmmode_update_fb (ScrnInfoPtr scrn, int width, int height) if (drmmode->fb_id != 0 && scrn->virtualX == width && scrn->virtualY == height) return TRUE; - if (!glamor_resize(scrn, width, height)) + if (!glamor_front_buffer_resize(scrn, width, height)) return FALSE; if (drmmode->fb_id != 0) drmModeRmFB(drmmode->fd, drmmode->fb_id); @@ -490,37 +472,33 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ScrnInfoPtr scrn = crtc->scrn; + ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); + GCPtr gc; if (drmmode_crtc->cursor == NULL) { - drmmode_crtc->cursor = glamor_create_cursor_argb(scrn, 64, 64); - if (drmmode_crtc->cursor == EGL_NO_IMAGE_KHR) + drmmode_crtc->cursor = calloc(1, sizeof(*drmmode_crtc->cursor)); + if (drmmode_crtc->cursor == NULL) { + ErrorF("Failed to allocate cursor.\n"); + return; + } + if (!glamor_create_cursor(scrn, drmmode_crtc->cursor, 64, 64)) { + free(drmmode_crtc->cursor); + drmmode_crtc->cursor = NULL; + ErrorF("Failed to create glamor cursor.\n"); return; - glGenTextures(1, &drmmode_crtc->cursor_tex); - glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, GL_NEAREST); - (glamor->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, drmmode_crtc->cursor); + } } - glBindTexture(GL_TEXTURE_2D, drmmode_crtc->cursor_tex); -#ifdef GLAMOR_GLES2 - /* XXX Actually, the image is BGRA not RGBA, so the r and b - * should be swapped. But as normally, they are the same value - * ignore this currently, don't want to let CPU to do the swizzle. - * considering to put this function to the glamor rendering directory. - * Thus we can reuse the shader to do this.*/ - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -#else - glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image); -#endif + gc = GetScratchGC (drmmode_crtc->cursor->cursor_pixmap->drawable.depth, screen); + if (!gc) + return; + + ValidateGC (&drmmode_crtc->cursor->cursor_pixmap->drawable, gc); + (*gc->ops->PutImage)(&drmmode_crtc->cursor->cursor_pixmap->drawable, gc, + 32, 0, 0, 64, 64, 0, ZPixmap, (char*)image); + FreeScratchGC (gc); } @@ -537,13 +515,12 @@ drmmode_hide_cursor (xf86CrtcPtr crtc) static void drmmode_show_cursor (xf86CrtcPtr crtc) { - ScrnInfoPtr scrn = crtc->scrn; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; uint32_t handle, stride; ErrorF("show cursor\n"); - glamor_cursor_handle(scrn, drmmode_crtc->cursor, &handle, &stride); + glamor_cursor_handle(drmmode_crtc->cursor, &handle, &stride); drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64); @@ -654,8 +631,9 @@ drmmode_crtc_destroy(xf86CrtcPtr crtc) ScrnInfoPtr scrn = crtc->scrn; if (drmmode_crtc->cursor) { drmmode_hide_cursor(crtc); - glDeleteTextures(1, &drmmode_crtc->cursor_tex); glamor_destroy_cursor(scrn, drmmode_crtc->cursor); + free(drmmode_crtc->cursor); + drmmode_crtc->cursor = NULL; } free(drmmode_crtc->cursor); crtc->driver_private = NULL; diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h index bed7bb921..3ffd48852 100644 --- a/hw/xfree86/glamor/glamor_ddx.h +++ b/hw/xfree86/glamor/glamor_ddx.h @@ -1,43 +1,23 @@ #ifndef GLAMOR_DDX_H #define GLAMOR_DDX_H -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#define EGL_DISPLAY_NO_X_MESA - -#if GLAMOR_GLES2 -#include -#include -#else -#include -#endif - -#define MESA_EGL_NO_X11_HEADERS -#include -#include - #include -#include "glamor_gl_dispatch.h" +#define GLAMOR_FOR_XORG 1 +#include struct glamor_ddx_screen_private { - EGLDisplay display; - EGLContext context; - EGLImageKHR root; struct gbm_bo *root_bo; struct gbm_bo *cursor_bo; - - EGLint major, minor; + struct gbm_device *gbm; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; int fd; int cpp; - struct gbm_device *gbm; +}; - PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; - PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; - PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; - struct glamor_gl_dispatch *dispatch; +struct glamor_gbm_cursor { + struct gbm_bo *cursor_bo; + PixmapPtr cursor_pixmap; }; inline static struct glamor_ddx_screen_private * @@ -46,15 +26,15 @@ glamor_ddx_get_screen_private(ScrnInfoPtr scrn) return (struct glamor_ddx_screen_private *) (scrn->driverPrivate); } -Bool glamor_resize(ScrnInfoPtr scrn, int width, int height); +Bool glamor_front_buffer_resize(ScrnInfoPtr scrn, int width, int height); void glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch); Bool glamor_load_cursor(ScrnInfoPtr scrn, - CARD32 *image, int width, int height); + int width, int height); -void glamor_cursor_handle(ScrnInfoPtr scrn, EGLImageKHR image, uint32_t *handle, uint32_t *pitch); -EGLImageKHR glamor_create_cursor_argb(ScrnInfoPtr scrn, int width, int height); -void glamor_destroy_cursor(ScrnInfoPtr scrn, EGLImageKHR cursor); +void glamor_cursor_handle(struct glamor_gbm_cursor *cursor, uint32_t *handle, uint32_t *pitch); +Bool glamor_create_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor, int width, int height); +void glamor_destroy_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor) ; Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); void drmmode_closefb(ScrnInfoPtr scrn); From f1c36c611efaa56e49758d8e8b19d07c10a8277e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 20 Sep 2011 17:10:50 +0800 Subject: [PATCH 216/462] glamor-ddx: Don't need to call preInit in screen_init. The previous implementation call preInit again to reopen the device if the device is closed by eglTerminate. Now we don't need it anymore, as glamor dix doesn't call eglTerminate any more when close screen. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor.c index 0dbee1806..f4b37ab6b 100644 --- a/hw/xfree86/glamor/glamor.c +++ b/hw/xfree86/glamor/glamor.c @@ -287,11 +287,8 @@ glamor_ddx_close_screen(int scrnIndex, ScreenPtr screen) glamor_fini(screen); glamor_close_egl_screen(screen); gbm_bo_destroy(glamor->root_bo); - drmmode_closefb(scrn); - glamor->fd = -1; - return TRUE; } @@ -301,22 +298,6 @@ glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); VisualPtr visual; - /* If serverGeneration != 1 then fd was closed during the last - time closing screen, actually in eglTerminate(). */ - - if (glamor->fd == -1 && serverGeneration != 1) { - glamor->fd = open(dri_device_name, O_RDWR); - if (glamor->fd == -1 ) { - ErrorF("Failed to open %s: %s\n", dri_device_name, strerror(errno)); - return FALSE; - } - if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Kernel modesetting setup failed\n"); - return FALSE; - } - - } glamor->gbm = gbm_create_device(glamor->fd); if (glamor->gbm == NULL) { From 483717484afb4ccf5b48483b3a21a9fe91213dd4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 20 Sep 2011 17:15:12 +0800 Subject: [PATCH 217/462] glamor-ddx: Destroy all the pixmap cursors when close current screen. As now we use pixmap to handle cursor, and pixmaps are related to current screen. If we close the screen, then we have to destroy all the related cursors. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor_crtc.c | 37 +++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index 854e81645..e86466abd 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -512,6 +512,34 @@ drmmode_hide_cursor (xf86CrtcPtr crtc) 0, 64, 64); } + +static void +_drmmode_destroy_cursor(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr + drmmode_crtc = crtc->driver_private; + + if (drmmode_crtc->cursor == NULL) + return; + drmmode_hide_cursor(crtc); + glamor_destroy_cursor(crtc->scrn, drmmode_crtc->cursor); + free(drmmode_crtc->cursor); + drmmode_crtc->cursor = NULL; +} + +static void +drmmode_destroy_cursor(ScrnInfoPtr scrn) +{ + int i; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + + for (i = 0; i < xf86_config->num_crtc; i++) + _drmmode_destroy_cursor(xf86_config->crtc[i]); +} + + + + static void drmmode_show_cursor (xf86CrtcPtr crtc) { @@ -629,12 +657,7 @@ drmmode_crtc_destroy(xf86CrtcPtr crtc) drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; ScrnInfoPtr scrn = crtc->scrn; - if (drmmode_crtc->cursor) { - drmmode_hide_cursor(crtc); - glamor_destroy_cursor(scrn, drmmode_crtc->cursor); - free(drmmode_crtc->cursor); - drmmode_crtc->cursor = NULL; - } + _drmmode_destroy_cursor(crtc); free(drmmode_crtc->cursor); crtc->driver_private = NULL; } @@ -1539,6 +1562,8 @@ void drmmode_closefb(ScrnInfoPtr scrn) drmmode_crtc = xf86_config->crtc[0]->driver_private; drmmode = drmmode_crtc->drmmode; + drmmode_destroy_cursor(scrn); + drmModeRmFB(drmmode->fd, drmmode->fb_id); drmmode->fb_id = 0; } From 937d3bcecf04305c01159f5c5084833f28014061 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 22 Sep 2011 13:39:01 +0800 Subject: [PATCH 218/462] glamor: Correct the version check for GLES2. If we are using GLES2, then the version number should be no less than 2.0 rather than no less than 1.3 which is for GL API. --- glamor/glamor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index ea4099ed2..a35fbee52 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -295,10 +295,17 @@ glamor_init(ScreenPtr screen, unsigned int flags) gl_version = glamor_gl_get_version(); +#ifndef GLAMOR_GLES2 if (gl_version < GLAMOR_GL_VERSION_ENCODE(1,3)) { - ErrorF("Require Opengl 1.3 or latter.\n"); + ErrorF("Require OpenGL version 1.3 or latter.\n"); goto fail; } +#else + if (gl_version < GLAMOR_GL_VERSION_ENCODE(2,0)) { + ErrorF("Require Open GLES2.0 or latter.\n"); + goto fail; + } +#endif glamor_gl_dispatch_init(screen, &glamor_priv->dispatch, gl_version); From df070205600cd736750d8a43426976a518b1fbae Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Sep 2011 16:01:03 +0800 Subject: [PATCH 219/462] ephyr-glamor: Set texture 0 to screen pixmap. In Xephyr, screen pixmap is different from other pixmap. It use fbo zero and texture zero. We initialize it during creating screen resources. Signed-off-by: Zhigang Gong --- hw/kdrive/ephyr/ephyr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index e2cd7a49d..5e217487f 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -718,8 +718,12 @@ ephyrCreateResources (ScreenPtr pScreen) ephyrShadowUpdate, ephyrWindowLinear); else { - if (ephyr_glamor) + if (ephyr_glamor) { + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; if (!glamor_glyphs_init(pScreen)) return FALSE; + glamor_set_screen_pixmap_texture(pScreen, screen->width, screen->height, 0); + } return ephyrSetInternalDamage(pScreen); } } From 1fb58860cc02d28545c66a916956a45918596870 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Sep 2011 16:05:52 +0800 Subject: [PATCH 220/462] ephyr-glamor: Implment gl disptach function for host glx. We should pass back the glXGetProcAddress to the underlying gl dispatch initialization function to get those gl function pointers. Signed-off-by: Zhigang Gong --- hw/kdrive/ephyr/hostx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 15dfc70ae..935c7c667 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -1532,3 +1532,15 @@ ephyr_glamor_paint_rect (EphyrScreenInfo screen, host_screen->win_width, host_screen->win_height); #endif } + +struct glamor_gl_dispatch; +extern Bool +glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, int gl_version, void* func); + +Bool +glamor_gl_dispatch_init(void *screen, struct glamor_gl_dispatch *dispatch, int gl_version) +{ + if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, glXGetProcAddress)) + return FALSE; + return TRUE; +} From fe4c95ce843afffed981ac8bb89ca433bd20f1e2 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Sep 2011 16:08:29 +0800 Subject: [PATCH 221/462] glamor: Refine the screen pixmap initialization for Xephyr. The previous implementation is to override the CreatePixmap firstly and assume the first call to CreatePixmap must be screen pixmap. This is not clean. Now Refine it to normal way. Let the Xephyr to set texture 0 to screen pixmap during creating screen resources. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 52 +++++++++---------------------------------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index a35fbee52..ee83fd3e9 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -73,8 +73,14 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) * to it. */ pixmap_priv->gl_fbo = 1; - pixmap_priv->gl_tex = 1; - glamor_pixmap_ensure_fb(pixmap); + if (tex != 0) { + glamor_pixmap_ensure_fb(pixmap); + pixmap_priv->gl_tex = 1; + } + else { + pixmap_priv->fb = 0; + pixmap_priv->gl_tex = 0; + } screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3, @@ -173,42 +179,6 @@ 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 = 0; - pixmap_priv->container = pixmap; - pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; - - screen->CreatePixmap = glamor_create_pixmap; - return pixmap; -} - - - - static Bool glamor_destroy_pixmap(PixmapPtr pixmap) { @@ -334,11 +304,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) screen->CreateGC = glamor_create_gc; glamor_priv->saved_create_pixmap = screen->CreatePixmap; - - if (flags & GLAMOR_HOSTX) - screen->CreatePixmap = glamor_create_screen_pixmap; - else - screen->CreatePixmap = glamor_create_pixmap; + screen->CreatePixmap = glamor_create_pixmap; glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; From 6a7ad1c92934b35eb2431c3e0f11c0c56a097dc9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Sep 2011 16:13:57 +0800 Subject: [PATCH 222/462] glamor-ddx: Don't double free the cursor memory. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/glamor_crtc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c index e86466abd..ce4f31f54 100644 --- a/hw/xfree86/glamor/glamor_crtc.c +++ b/hw/xfree86/glamor/glamor_crtc.c @@ -516,8 +516,7 @@ drmmode_hide_cursor (xf86CrtcPtr crtc) static void _drmmode_destroy_cursor(xf86CrtcPtr crtc) { - drmmode_crtc_private_ptr - drmmode_crtc = crtc->driver_private; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; if (drmmode_crtc->cursor == NULL) return; @@ -654,11 +653,8 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, static void drmmode_crtc_destroy(xf86CrtcPtr crtc) { - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - ScrnInfoPtr scrn = crtc->scrn; _drmmode_destroy_cursor(crtc); - free(drmmode_crtc->cursor); crtc->driver_private = NULL; } From 101b69dddff6cc538cb369c70377bbad825aa765 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Sep 2011 16:33:52 +0800 Subject: [PATCH 223/462] glamor: Check libgbm if enable glamor ddx. Signed-off-by: Zhigang Gong --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 80daf828b..bf174351f 100644 --- a/configure.ac +++ b/configure.ac @@ -803,6 +803,7 @@ LIBDBUS="dbus-1 >= 1.0" LIBPIXMAN="pixman-1 >= 0.21.8" LIBEGL="egl" LIBGLESV2="glesv2" +LIBGBM="gbm" dnl Pixman is always required, but we separate it out so we can link dnl specific modules against it PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) @@ -1796,6 +1797,7 @@ if test "x$GLAMOR" = xyes; then if test "x$GLAMOR_DDX" = xyes; then AC_DEFINE(GLAMOR_DDX,1,[Enable glamor ddx driver]) PKG_CHECK_MODULES(EGL, $LIBEGL) + PKG_CHECK_MODULES(EGL, $LIBGBM) REQUIRED_LIBS="$REQUIRED_LIBS $LIBEGL" fi fi From 284328a6beb0bd0ab6653973ce52b5a68b4e791f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Sep 2011 17:04:56 +0800 Subject: [PATCH 224/462] glamor-ddx: Rename glamor.c to glamor_ddx.c. As glamor's dix module already has a glamor.c, rename this glamor.c to other name to avoid file name conflict which may confuse gdb. Signed-off-by: Zhigang Gong --- hw/xfree86/glamor/Makefile.am | 2 +- hw/xfree86/glamor/{glamor.c => glamor_ddx.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename hw/xfree86/glamor/{glamor.c => glamor_ddx.c} (100%) diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am index fbd561cd1..1d729f46b 100644 --- a/hw/xfree86/glamor/Makefile.am +++ b/hw/xfree86/glamor/Makefile.am @@ -20,7 +20,7 @@ glamor_la_LDFLAGS = -module -avoid-version \ glamor_ladir = $(moduledir)/drivers glamor_la_SOURCES = \ - glamor.c \ + glamor_ddx.c \ glamor_crtc.c \ glamor_ddx.h diff --git a/hw/xfree86/glamor/glamor.c b/hw/xfree86/glamor/glamor_ddx.c similarity index 100% rename from hw/xfree86/glamor/glamor.c rename to hw/xfree86/glamor/glamor_ddx.c From 7982eca622bbc4b6a4845801a77da8a16138004a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Dec 2013 11:16:15 -0800 Subject: [PATCH 225/462] Revert changes outside of glamor from the glamor branch. We want to merge the external glamor code to the xserver, with the internal history retained. However, we don't want a bunch of non-building changes along the way, so remove all the build system and support code outside of glamor for now. --- Makefile.am | 6 - README | 39 +- configure.ac | 45 +- hw/kdrive/ephyr/Makefile.am | 16 +- hw/kdrive/ephyr/ephyr.c | 16 +- hw/kdrive/ephyr/ephyr.h | 7 - hw/kdrive/ephyr/ephyr_glamor.c | 67 -- hw/kdrive/ephyr/ephyrinit.c | 11 - hw/kdrive/ephyr/hostx.c | 103 +- hw/kdrive/ephyr/hostx.h | 3 - hw/xfree86/Makefile.am | 8 +- hw/xfree86/common/Makefile.am | 8 +- hw/xfree86/common/xf86pciBus.c | 6 +- hw/xfree86/dixmods/Makefile.am | 15 +- hw/xfree86/dixmods/glamor_module.c | 47 - hw/xfree86/glamor/Makefile.am | 28 - hw/xfree86/glamor/glamor_crtc.c | 1565 ---------------------------- hw/xfree86/glamor/glamor_ddx.c | 531 ---------- hw/xfree86/glamor/glamor_ddx.h | 42 - include/xorg-config.h.in | 11 - 20 files changed, 15 insertions(+), 2559 deletions(-) delete mode 100644 hw/kdrive/ephyr/ephyr_glamor.c delete mode 100644 hw/xfree86/dixmods/glamor_module.c delete mode 100644 hw/xfree86/glamor/Makefile.am delete mode 100644 hw/xfree86/glamor/glamor_crtc.c delete mode 100644 hw/xfree86/glamor/glamor_ddx.c delete mode 100644 hw/xfree86/glamor/glamor_ddx.h diff --git a/Makefile.am b/Makefile.am index 632258eec..cea140bea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,10 +17,6 @@ if RECORD RECORD_DIR=record endif -if GLAMOR -GLAMOR_DIR=glamor -endif - SUBDIRS = \ doc \ man \ @@ -42,7 +38,6 @@ SUBDIRS = \ $(COMPOSITE_DIR) \ $(GLX_DIR) \ exa \ - $(GLAMOR_DIR) \ config \ hw \ test @@ -93,7 +88,6 @@ DIST_SUBDIRS = \ composite \ glx \ exa \ - glamor \ config \ hw \ test diff --git a/README b/README index c240ac775..b2499a059 100644 --- a/README +++ b/README @@ -1,41 +1,4 @@ - Glamor setup - -1. Prerequirement. -Please install makedepend and libudev-devel firstly. - -2. Build xserver-glamor. - -Then do the following steps one by one. -2.1. get latest glamor at github. - -2.2 Setup xorg development environment, use xserver-glamor to - replace the official xserver. - Here is the link of how to setup xorg development environment: - http://www.x.org/wiki/ModularDevelopersGuide - - For most of the packages, we prefer latest git version. Especially - for the mesa package. - - When build mesa, use the following parameters: (assume you want to - install the experimental xorg to /opt/gfx-test) -#mesa/./autogen.sh --prefix=/opt/gfx-test --with-egl-platforms=drm --disable-gallium --disable-gallium-egl - - build xserver-glamor as below: -#xserver-glamor/./autogen.sh --disable-glx --enable-kdrive --enable-xephyr - - Once you finish all the building process, you can have a try as below: -xserver-glamor#startx -- `pwd`/hw/xfree86/Xorg If you can find the - following messages on the console, then everything should work correctly. -Mesa: Initializing x86-64 optimizations - - -3. Restrictions: - -Currently, glamor doesn't support glx extension, will be fixed in the future. - -Glamor setup done. - - X Server + X Server The X server accepts requests from client applications to create windows, which are (normally rectangular) "virtual screens" that the client program diff --git a/configure.ac b/configure.ac index bf174351f..b0d26435a 100644 --- a/configure.ac +++ b/configure.ac @@ -646,8 +646,6 @@ AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest serv AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) -AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no]) -AC_ARG_ENABLE(glamor-ddx, AS_HELP_STRING([--enable-glamor-ddx], [Build glamor ddx (default: no)]), [GLAMOR_DDX=$enableval], [GLAMOR_DDX=no]) dnl kdrive and its subsystems AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) AC_ARG_ENABLE(xephyr, AS_HELP_STRING([--enable-xephyr], [Build the kdrive Xephyr server (default: auto)]), [XEPHYR=$enableval], [XEPHYR=auto]) @@ -657,8 +655,6 @@ dnl kdrive options AC_ARG_ENABLE(kdrive-kbd, AS_HELP_STRING([--enable-kdrive-kbd], [Build kbd driver for kdrive (default: auto)]), [KDRIVE_KBD=$enableval], [KDRIVE_KBD=auto]) AC_ARG_ENABLE(kdrive-mouse, AC_HELP_STRING([--enable-kdrive-mouse], [Build mouse driver for kdrive (default: auto)]), [KDRIVE_MOUSE=$enableval], [KDRIVE_MOUSE=auto]) AC_ARG_ENABLE(kdrive-evdev, AC_HELP_STRING([--enable-kdrive-evdev], [Build evdev driver for kdrive (default: auto)]), [KDRIVE_EVDEV=$enableval], [KDRIVE_EVDEV=auto]) -dnl glamor options -AC_ARG_ENABLE(glamor-gles2, AS_HELP_STRING([--enable-glamor-gles2], [Build glamor based on gles2 (default: no)]), [GLAMOR_GLES2=$enableval], [GLAMOR_GLES2=no]) dnl chown/chmod to be setuid root as part of build @@ -801,9 +797,7 @@ LIBUDEV="libudev >= 143" LIBSELINUX="libselinux >= 2.0.86" LIBDBUS="dbus-1 >= 1.0" LIBPIXMAN="pixman-1 >= 0.21.8" -LIBEGL="egl" -LIBGLESV2="glesv2" -LIBGBM="gbm" + dnl Pixman is always required, but we separate it out so we can link dnl specific modules against it PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) @@ -1771,37 +1765,6 @@ AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) -dnl glamor - -if [test "x$XEPHYR" = xyes || test "x$GLAMOR_DDX" = xyes] ; then - GLAMOR=yes -fi - -AM_CONDITIONAL([GLAMOR], [test "x$GLAMOR" = xyes]) -AM_CONDITIONAL([GLAMOR_GLES2], [test "x$GLAMOR_GLES2" = xyes]) -AM_CONDITIONAL([GLAMOR_DDX], [test "x$GLAMOR_DDX" = xyes]) - -if test "x$GLAMOR" = xyes; then - AC_DEFINE(GLAMOR,1,[Build Glamor]) - - if test "x$GLAMOR_GLES2" = xyes; then - AC_DEFINE(GLAMOR_GLES2,1,[Build glamor over GLES2]) - PKG_CHECK_MODULES(GLESV2, $LIBGLESV2) - REQUIRED_LIBS="$REQUIRED_LIBS $LIBGLESV2" - else - AC_DEFINE(GLAMOR_GL,1,[Build glamor over GL]) - PKG_CHECK_MODULES(GL, $LIBGL) - REQUIRED_LIBS="$REQUIRED_LIBS $LIBGL" - fi - - if test "x$GLAMOR_DDX" = xyes; then - AC_DEFINE(GLAMOR_DDX,1,[Enable glamor ddx driver]) - PKG_CHECK_MODULES(EGL, $LIBEGL) - PKG_CHECK_MODULES(EGL, $LIBGBM) - REQUIRED_LIBS="$REQUIRED_LIBS $LIBEGL" - fi -fi - dnl XWin DDX AC_MSG_CHECKING([whether to build XWin DDX]) @@ -2035,10 +1998,6 @@ if test "$KDRIVE" = yes; then if test "x$DRI" = xyes && test "x$GLX" = xyes; then XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm" fi - # The glamor stuff requires libGL, but that conflicts with GLX currently. - if test "x$GLX" = xno; then - XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS gl" - fi PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"]) if test "x$XEPHYR" = xauto; then @@ -2174,7 +2133,6 @@ Xext/Makefile Xi/Makefile xfixes/Makefile exa/Makefile -glamor/Makefile hw/Makefile hw/xfree86/Makefile hw/xfree86/common/Makefile @@ -2212,7 +2170,6 @@ hw/xfree86/utils/Makefile hw/xfree86/utils/man/Makefile hw/xfree86/utils/cvt/Makefile hw/xfree86/utils/gtf/Makefile -hw/xfree86/glamor/Makefile hw/dmx/config/Makefile hw/dmx/config/man/Makefile hw/dmx/doc/Makefile diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index 744604eea..9d9b64ee5 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -7,8 +7,7 @@ INCLUDES = \ @XEPHYR_CFLAGS@ \ @DRIPROTO_CFLAGS@ \ -I$(top_srcdir) \ - -I$(top_srcdir)/exa \ - -I$(top_srcdir)/glamor + -I$(top_srcdir)/exa if XV LIBXEPHYR_HOSTXV=libxephyr-hostxv.la @@ -48,7 +47,6 @@ XEPHYR_SRCS = \ ephyr.h \ ephyrlog.h \ ephyr_draw.c \ - ephyr_glamor.c \ os.c libxephyr_hostx_la_SOURCES = $(HOSTX_SRCS) @@ -66,28 +64,18 @@ libxephyr_la_SOURCES = $(XEPHYR_SRCS) Xephyr_SOURCES = \ ephyrinit.c -if GLAMOR_GLES2 -GLAMOR_GL_LIB = -lGLESv2 -else -GLAMOR_GL_LIB = -lGL -endif - Xephyr_LDADD = \ libxephyr.la \ libxephyr-hostx.la \ $(LIBXEPHYR_HOSTXV) \ $(LIBXEPHYR_HOSTDRI) \ $(top_builddir)/exa/libexa.la \ - $(top_builddir)/glamor/libglamor.la \ @KDRIVE_LIBS@ \ - @XEPHYR_LIBS@ \ - $(GLAMOR_GL_LIB) + @XEPHYR_LIBS@ Xephyr_DEPENDENCIES = \ libxephyr.la \ libxephyr-hostx.la \ - $(top_builddir)/exa/libexa.la \ - $(top_builddir)/glamor/libglamor.la \ $(LIBXEPHYR_HOSTXV) \ $(LIBXEPHYR_HOSTDRI) \ @KDRIVE_LOCAL_LIBS@ diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 5e217487f..7ebf1c253 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -394,7 +394,7 @@ ephyrSetInternalDamage (ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; PixmapPtr pPixmap = NULL; - + scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0, (DamageDestroyFunc) 0, DamageReportNone, @@ -669,9 +669,7 @@ ephyrInitScreen (ScreenPtr pScreen) } if (!ephyrNoDRI) { ephyrDRIExtensionInit (pScreen) ; -#if 0 ephyrHijackGLXExtension () ; -#endif } #endif @@ -684,7 +682,6 @@ ephyrInitScreen (ScreenPtr pScreen) return TRUE; } - Bool ephyrFinishInitScreen (ScreenPtr pScreen) { @@ -701,7 +698,6 @@ ephyrFinishInitScreen (ScreenPtr pScreen) return TRUE; } -extern Bool ephyr_glamor; Bool ephyrCreateResources (ScreenPtr pScreen) @@ -712,20 +708,14 @@ ephyrCreateResources (ScreenPtr pScreen) EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", pScreen, pScreen->myNum, scrpriv->shadow); + if (scrpriv->shadow) return KdShadowSet (pScreen, scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear); - else { - if (ephyr_glamor) { - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - if (!glamor_glyphs_init(pScreen)) return FALSE; - glamor_set_screen_pixmap_texture(pScreen, screen->width, screen->height, 0); - } + else return ephyrSetInternalDamage(pScreen); - } } void diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index 9dcde8d56..23848004c 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -196,13 +196,6 @@ ephyrDrawDisable(ScreenPtr pScreen); void ephyrDrawFini(ScreenPtr pScreen); -/* ephyr_glamor.c */ -Bool ephyr_glamor_init(ScreenPtr pScreen); -void ephyr_glamor_enable(ScreenPtr pScreen); -void ephyr_glamor_disable(ScreenPtr pScreen); -void ephyr_glamor_fini(ScreenPtr pScreen); -void ephyr_glamor_host_paint_rect(ScreenPtr pScreen); - /*ephyvideo.c*/ Bool ephyrInitVideo(ScreenPtr pScreen) ; diff --git a/hw/kdrive/ephyr/ephyr_glamor.c b/hw/kdrive/ephyr/ephyr_glamor.c deleted file mode 100644 index 53bfbb995..000000000 --- a/hw/kdrive/ephyr/ephyr_glamor.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright © 2008 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Eric Anholt - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "ephyr.h" -#include "glamor.h" - -/** - * This function initializes EXA to use the fake acceleration implementation - * which just falls through to software. The purpose is to have a reliable, - * correct driver with which to test changes to the EXA core. - */ -Bool -ephyr_glamor_init(ScreenPtr screen) -{ - KdScreenPriv(screen); - KdScreenInfo *kd_screen = pScreenPriv->screen; - - ephyr_glamor_host_create_context(kd_screen); - - glamor_init(screen, GLAMOR_HOSTX); - - return TRUE; -} - -void -ephyr_glamor_enable(ScreenPtr screen) -{ -} - -void -ephyr_glamor_disable(ScreenPtr screen) -{ -} - -void -ephyr_glamor_fini(ScreenPtr screen) -{ - glamor_fini(screen); -} diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 9155d0861..b674bb8d0 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -31,7 +31,6 @@ extern Window EphyrPreExistingHostWin; extern Bool EphyrWantGrayScale; -extern Bool ephyr_glamor; extern Bool kdHasPointer; extern Bool kdHasKbd; @@ -118,7 +117,6 @@ ddxUseMsg (void) ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); ErrorF("-grayscale Simulate 8bit grayscale\n"); - ErrorF("-glamor Enable 2D acceleration using glamor\n"); ErrorF("-fakexa Simulate acceleration using software rendering\n"); ErrorF("-verbosity Set log verbosity level\n"); #ifdef GLXEXT @@ -222,15 +220,6 @@ ddxProcessArgument (int argc, char **argv, int i) EphyrWantGrayScale = 1; return 1; } - else if (!strcmp (argv[i], "-glamor")) - { - ephyr_glamor = TRUE; - ephyrFuncs.initAccel = ephyr_glamor_init; - ephyrFuncs.enableAccel = ephyr_glamor_enable; - ephyrFuncs.disableAccel = ephyr_glamor_disable; - ephyrFuncs.finiAccel = ephyr_glamor_fini; - return 1; - } else if (!strcmp (argv[i], "-fakexa")) { ephyrFuncs.initAccel = ephyrDrawInit; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 935c7c667..4caf4516d 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -46,7 +46,6 @@ #include #include /* for memset */ #include -#include #include #include @@ -62,7 +61,6 @@ #include #endif /* XF86DRI */ #include "ephyrlog.h" -#include "GL/glx.h" #ifdef XF86DRI extern Bool XF86DRIQueryExtension (Display *dpy, @@ -97,7 +95,6 @@ struct EphyrHostXVars Display *dpy; int screen; Visual *visual; - XVisualInfo *visual_info; Window winroot; GC gc; int depth; @@ -126,14 +123,10 @@ extern int monitorResolution; char *ephyrResName = NULL; int ephyrResNameFromCmd = 0; char *ephyrTitle = NULL; -Bool ephyr_glamor = FALSE; static void hostx_set_fullscreen_hint(void); -static void -ephyr_glamor_get_visual(void); - /* X Error traps */ static int trapped_error_code = 0; @@ -369,11 +362,8 @@ hostx_init (void) HostX.winroot = RootWindow(HostX.dpy, HostX.screen); HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); HostX.depth = DefaultDepth(HostX.dpy, HostX.screen); - if (ephyr_glamor) { - ephyr_glamor_get_visual(); - } else { - HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); - } + HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); + class_hint = XAllocClassHint(); for (index = 0 ; index < HostX.n_screens ; index++) @@ -767,11 +757,6 @@ hostx_screen_init (EphyrScreenInfo screen, static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, int x, int y, int width, int height); -static void -ephyr_glamor_paint_rect (EphyrScreenInfo screen, - int sx, int sy, - int dx, int dy, - int width, int height); void hostx_paint_rect (EphyrScreenInfo screen, @@ -783,11 +768,6 @@ hostx_paint_rect (EphyrScreenInfo screen, EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ; - if (ephyr_glamor) { - ephyr_glamor_paint_rect(screen, sx, sy, dx, dy, width, height); - return; - } - /* * Copy the image data updated by the shadow layer * on to the window @@ -1465,82 +1445,3 @@ hostx_has_glx (void) } #endif /* XF86DRI */ - -static void -ephyr_glamor_get_visual(void) -{ - Display *dpy = HostX.dpy; - int attribs[] = {GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, 1, - None}; - XVisualInfo *visual_info; - int event_base = 0, error_base = 0; - - if (!glXQueryExtension (dpy, &event_base, &error_base)) - errx(1, "Couldn't find GLX extension\n"); - - visual_info = glXChooseVisual(dpy, DefaultScreen(dpy), attribs); - if (visual_info == NULL) - errx(1, "Couldn't get RGB visual\n"); - - HostX.visual_info = visual_info; - HostX.visual = visual_info->visual; -} - -void -ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen) -{ - Display *dpy = HostX.dpy; - GLXContext ctx; - struct EphyrHostScreen *host_screen; - - host_screen = host_screen_from_screen_info(ephyr_screen); - - ctx = glXCreateContext(dpy, HostX.visual_info, NULL, True); - if (ctx == NULL) - errx(1, "glXCreateContext failed\n"); - - if (!glXMakeCurrent(dpy, host_screen->win, ctx)) - errx(1, "glXMakeCurrent failed\n"); -} - -static void -ephyr_glamor_paint_rect (EphyrScreenInfo screen, - int sx, int sy, - int dx, int dy, - int width, int height) -{ - struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); - static PFNGLXCOPYSUBBUFFERMESAPROC pglXCopySubBufferMESA = NULL; - - if (!pglXCopySubBufferMESA) { - pglXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC) - glXGetProcAddressARB((const GLubyte*)"glXCopySubBufferMESA"); - assert(pglXCopySubBufferMESA); - } - - /* Always copy the full screen until we get things rendering correctly. */ -#if 0 - pglXCopySubBufferMESA(HostX.dpy, host_screen->win, - sx, sy, width, height); -#else - pglXCopySubBufferMESA(HostX.dpy, host_screen->win, - 0, 0, - host_screen->win_width, host_screen->win_height); -#endif -} - -struct glamor_gl_dispatch; -extern Bool -glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, int gl_version, void* func); - -Bool -glamor_gl_dispatch_init(void *screen, struct glamor_gl_dispatch *dispatch, int gl_version) -{ - if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, glXGetProcAddress)) - return FALSE; - return TRUE; -} diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index d5cb0faa6..42578576a 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -261,7 +261,4 @@ int hostx_has_dri (void) ; int hostx_has_glx (void) ; #endif /* XF86DRI */ -/* ephyr_glamor_host.c */ -void ephyr_glamor_host_create_context(EphyrScreenInfo ephyr_screen); - #endif /*_XLIBS_STUFF_H_*/ diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am index f76a36155..e3ef14fc1 100644 --- a/hw/xfree86/Makefile.am +++ b/hw/xfree86/Makefile.am @@ -27,16 +27,12 @@ if INT10MODULE INT10_SUBDIR = int10 endif -if GLAMOR -GLAMOR_DIR=glamor -endif - -SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw $(GLAMOR_DIR) os-support parser \ +SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw os-support parser \ ramdac shadowfb $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \ loader dixmods exa modes \ $(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) doc man -DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw $(GLAMOR_DIR) os-support \ +DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \ parser ramdac shadowfb vbe vgahw xaa \ loader dixmods dri dri2 exa modes \ utils doc man diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am index 173d76570..c031d4be3 100644 --- a/hw/xfree86/common/Makefile.am +++ b/hw/xfree86/common/Makefile.am @@ -89,10 +89,4 @@ if LNXACPI XORG_CFLAGS += -DHAVE_ACPI endif -if GLAMOR_DDX -GLAMOR_DDX_CFLAGS = -DGLAMOR_DDX -endif - -AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_DDX_CFLAGS) - - +AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index 7ab3f2875..447b19229 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -1118,11 +1118,7 @@ videoPtrToDriverList(struct pci_device *dev, } else if (dev->device_id == 0x8108) { break; /* "hooray" for poulsbo */ } else { -#ifdef GLAMOR_DDX - driverList[0] = "glamor"; -#else - driverList[0] = "intel"; -#endif + driverList[0] = "intel"; } break; case 0x102b: driverList[0] = "mga"; break; diff --git a/hw/xfree86/dixmods/Makefile.am b/hw/xfree86/dixmods/Makefile.am index ba4aeb402..1a162ab1c 100644 --- a/hw/xfree86/dixmods/Makefile.am +++ b/hw/xfree86/dixmods/Makefile.am @@ -14,14 +14,9 @@ if RECORD RECORDMOD = librecord.la endif -if GLAMOR -LIBGLAMOR_DIX = libglamor_dix.la -endif - module_LTLIBRARIES = libfb.la \ libwfb.la \ - libshadow.la \ - $(LIBGLAMOR_DIX) + libshadow.la extsmoduledir = $(moduledir)/extensions extsmodule_LTLIBRARIES = $(RECORDMOD) \ @@ -34,17 +29,11 @@ INCLUDES = @XORG_INCS@ \ -I$(top_srcdir)/hw/xfree86/loader \ -I$(top_srcdir)/miext/shadow \ -I$(top_srcdir)/glx - libdbe_la_LDFLAGS = -avoid-version libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la libdbe_la_SOURCES = dbemodule.c -if GLAMOR -libglamor_dix_la_LDFLAGS = -avoid-version -libglamor_dix_la_LIBADD = $(top_builddir)/glamor/libglamor.la -libglamor_dix_la_SOURCES = glamor_module.c $(top_srcdir)/glamor/glamor_egl.c -libglamor_dix_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/glamor $(LIBDRM_CFLAGS) -endif + libfb_la_LDFLAGS = -avoid-version libfb_la_LIBADD = $(top_builddir)/fb/libfb.la libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c diff --git a/hw/xfree86/dixmods/glamor_module.c b/hw/xfree86/dixmods/glamor_module.c deleted file mode 100644 index ee2dba871..000000000 --- a/hw/xfree86/dixmods/glamor_module.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 1998 The XFree86 Project, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the XFree86 Project shall - * not be used in advertising or otherwise to promote the sale, use or other - * dealings in this Software without prior written authorization from the - * XFree86 Project. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86Module.h" - -static XF86ModuleVersionInfo VersRec = -{ - "glamor_dix", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - 1, 0, 0, - ABI_CLASS_ANSIC, /* Only need the ansic layer */ - ABI_ANSIC_VERSION, - MOD_CLASS_NONE, - {0,0,0,0} /* signature, to be patched into the file by a tool */ -}; - -_X_EXPORT XF86ModuleData glamor_dixModuleData = { &VersRec, NULL, NULL }; diff --git a/hw/xfree86/glamor/Makefile.am b/hw/xfree86/glamor/Makefile.am deleted file mode 100644 index 1d729f46b..000000000 --- a/hw/xfree86/glamor/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -glamor_la_LTLIBRARIES = glamor.la -glamor_la_CFLAGS = \ - -DHAVE_XORG_CONFIG_H \ - @DIX_CFLAGS@ @XORG_CFLAGS@ @LIBDRM_CFLAGS@ \ - -I$(top_srcdir)/hw/xfree86/common \ - -I$(top_srcdir)/hw/xfree86/os-support/bus \ - -I$(top_srcdir)/hw/xfree86/parser \ - -I$(top_srcdir)/hw/xfree86/modes \ - -I$(top_srcdir)/hw/xfree86/ddc \ - -I$(top_srcdir)/hw/xfree86/ramdac \ - -I$(top_srcdir)/hw/xfree86/i2c \ - -I$(top_srcdir)/glamor - -if GLAMOR_GLES2 -glamor_la_CFLAGS+=-DGLAMOR_GLES2 -endif - -glamor_la_LDFLAGS = -module -avoid-version \ - $(EGL_LIBS) - -glamor_ladir = $(moduledir)/drivers -glamor_la_SOURCES = \ - glamor_ddx.c \ - glamor_crtc.c \ - glamor_ddx.h - -glamor_la_DEPENDENCIES = \ - $(top_builddir)/glamor/libglamor.la diff --git a/hw/xfree86/glamor/glamor_crtc.c b/hw/xfree86/glamor/glamor_crtc.c deleted file mode 100644 index ce4f31f54..000000000 --- a/hw/xfree86/glamor/glamor_crtc.c +++ /dev/null @@ -1,1565 +0,0 @@ -/* - * Copyright © 2007 Red Hat, Inc. - * Copyright © 2010 Intel Corporation. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including - * the next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Dave Airlie - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "glamor_ddx.h" - -typedef struct { - int fd; - uint32_t fb_id; - drmModeResPtr mode_res; - int cpp; - - drmEventContext event_context; - void *event_data; - int old_fb_id; - int flip_count; -} drmmode_rec, *drmmode_ptr; - -typedef struct { - drmmode_ptr drmmode; - drmModeCrtcPtr mode_crtc; - uint32_t rotate_fb_id; - struct glamor_gbm_cursor *cursor; -} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; - -typedef struct { - drmModePropertyPtr mode_prop; - uint64_t value; - int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */ - Atom *atoms; -} drmmode_prop_rec, *drmmode_prop_ptr; - -struct fixed_panel_lvds { - int hdisplay; - int vdisplay; -}; -typedef struct { - drmmode_ptr drmmode; - int output_id; - drmModeConnectorPtr mode_output; - drmModeEncoderPtr mode_encoder; - drmModePropertyBlobPtr edid_blob; - int num_props; - drmmode_prop_ptr props; - void *private_data; - int dpms_mode; - char *backlight_iface; - int backlight_active_level; - int backlight_max; -} drmmode_output_private_rec, *drmmode_output_private_ptr; - -static void -drmmode_output_dpms(xf86OutputPtr output, int mode); -static Bool -drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height); - -#define BACKLIGHT_CLASS "/sys/class/backlight" - -/* - * List of available kernel interfaces in priority order - */ -static char *backlight_interfaces[] = { - "asus-laptop", - "eeepc", - "thinkpad_screen", - "acpi_video1", - "acpi_video0", - "fujitsu-laptop", - "sony", - "samsung", - NULL, -}; -/* - * Must be long enough for BACKLIGHT_CLASS + '/' + longest in above table + - * '/' + "max_backlight" - */ -#define BACKLIGHT_PATH_LEN 80 -/* Enough for 10 digits of backlight + '\n' + '\0' */ -#define BACKLIGHT_VALUE_LEN 12 - -static void -drmmode_backlight_set(xf86OutputPtr output, int level) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; - int fd, len, ret; - - if (level > drmmode_output->backlight_max) - level = drmmode_output->backlight_max; - if (! drmmode_output->backlight_iface || level < 0) - return; - - len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level); - sprintf(path, "%s/%s/brightness", - BACKLIGHT_CLASS, drmmode_output->backlight_iface); - fd = open(path, O_RDWR); - if (fd == -1) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s for backlight " - "control: %s\n", path, strerror(errno)); - return; - } - - ret = write(fd, val, len); - if (ret == -1) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "write to %s for backlight " - "control failed: %s\n", path, strerror(errno)); - } - - close(fd); -} - -static int -drmmode_backlight_get(xf86OutputPtr output) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; - int fd, level; - - if (! drmmode_output->backlight_iface) - return -1; - - sprintf(path, "%s/%s/actual_brightness", - BACKLIGHT_CLASS, drmmode_output->backlight_iface); - fd = open(path, O_RDONLY); - if (fd == -1) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s " - "for backlight control: %s\n", path, strerror(errno)); - return -1; - } - - memset(val, 0, sizeof(val)); - if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) { - close(fd); - return -1; - } - - close(fd); - - level = atoi(val); - if (level > drmmode_output->backlight_max) - level = drmmode_output->backlight_max; - if (level < 0) - level = -1; - return level; -} - -static int -drmmode_backlight_get_max(xf86OutputPtr output) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; - int fd, max = 0; - - sprintf(path, "%s/%s/max_brightness", - BACKLIGHT_CLASS, drmmode_output->backlight_iface); - fd = open(path, O_RDONLY); - if (fd == -1) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s " - "for backlight control: %s\n", path, strerror(errno)); - return 0; - } - - memset(val, 0, sizeof(val)); - if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) { - close(fd); - return -1; - } - - close(fd); - - max = atoi(val); - if (max <= 0) - max = -1; - return max; -} - -static void -drmmode_backlight_init(xf86OutputPtr output) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - char path[BACKLIGHT_PATH_LEN]; - struct stat buf; - int i; - - for (i = 0; backlight_interfaces[i] != NULL; i++) { - sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]); - if (!stat(path, &buf)) { - drmmode_output->backlight_iface = backlight_interfaces[i]; - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, - "found backlight control interface %s\n", path); - drmmode_output->backlight_max = drmmode_backlight_get_max(output); - drmmode_output->backlight_active_level = drmmode_backlight_get(output); - return; - } - } - drmmode_output->backlight_iface = NULL; -} - - -static void -drmmode_ConvertFromKMode(ScrnInfoPtr scrn, - drmModeModeInfoPtr kmode, - DisplayModePtr mode) -{ - memset(mode, 0, sizeof(DisplayModeRec)); - mode->status = MODE_OK; - - mode->Clock = kmode->clock; - - mode->HDisplay = kmode->hdisplay; - mode->HSyncStart = kmode->hsync_start; - mode->HSyncEnd = kmode->hsync_end; - mode->HTotal = kmode->htotal; - mode->HSkew = kmode->hskew; - - mode->VDisplay = kmode->vdisplay; - mode->VSyncStart = kmode->vsync_start; - mode->VSyncEnd = kmode->vsync_end; - mode->VTotal = kmode->vtotal; - mode->VScan = kmode->vscan; - - mode->Flags = kmode->flags; //& FLAG_BITS; - mode->name = strdup(kmode->name); - - if (kmode->type & DRM_MODE_TYPE_DRIVER) - mode->type = M_T_DRIVER; - if (kmode->type & DRM_MODE_TYPE_PREFERRED) - mode->type |= M_T_PREFERRED; - xf86SetModeCrtc (mode, scrn->adjustFlags); -} - -static void -drmmode_ConvertToKMode(ScrnInfoPtr scrn, - drmModeModeInfoPtr kmode, - DisplayModePtr mode) -{ - memset(kmode, 0, sizeof(*kmode)); - - kmode->clock = mode->Clock; - kmode->hdisplay = mode->HDisplay; - kmode->hsync_start = mode->HSyncStart; - kmode->hsync_end = mode->HSyncEnd; - kmode->htotal = mode->HTotal; - kmode->hskew = mode->HSkew; - - kmode->vdisplay = mode->VDisplay; - kmode->vsync_start = mode->VSyncStart; - kmode->vsync_end = mode->VSyncEnd; - kmode->vtotal = mode->VTotal; - kmode->vscan = mode->VScan; - - kmode->flags = mode->Flags; //& FLAG_BITS; - if (mode->name) - strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); - kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; - -} - -static void -drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode) -{ - -} - -static Bool -drmmode_update_fb (ScrnInfoPtr scrn, int width, int height) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - drmmode_crtc_private_ptr - drmmode_crtc = xf86_config->crtc[0]->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - uint32_t handle, pitch; - int ret; - - if (drmmode->fb_id != 0 && - scrn->virtualX == width && scrn->virtualY == height) - return TRUE; - if (!glamor_front_buffer_resize(scrn, width, height)) - return FALSE; - if (drmmode->fb_id != 0) - drmModeRmFB(drmmode->fd, drmmode->fb_id); - glamor_frontbuffer_handle(scrn, &handle, &pitch); - ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, - scrn->bitsPerPixel, pitch /** drmmode->cpp*/, - handle, &drmmode->fb_id); - if (ret) - /* FIXME: Undo glamor_resize() */ - return FALSE; - - return TRUE; -} - -static Bool -drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, - Rotation rotation, int x, int y) -{ - ScrnInfoPtr scrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - int saved_x, saved_y; - Rotation saved_rotation; - DisplayModeRec saved_mode; - uint32_t *output_ids; - int output_count = 0; - int ret = TRUE; - int i; - int fb_id; - uint32_t handle, pitch; - drmModeModeInfo kmode; - - if (drmmode->fb_id == 0) { - - glamor_frontbuffer_handle(scrn, &handle, &pitch); - ret = drmModeAddFB(drmmode->fd, - scrn->virtualX, scrn->virtualY, - scrn->depth, scrn->bitsPerPixel, - pitch, handle, - &drmmode->fb_id); - if (ret < 0) { - ErrorF("failed to add fb\n"); - return FALSE; - } - } - - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - saved_rotation = crtc->rotation; - - crtc->mode = *mode; - crtc->x = x; - crtc->y = y; - crtc->rotation = rotation; - - output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); - if (!output_ids) { - ret = FALSE; - goto done; - } - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - drmmode_output_private_ptr drmmode_output; - - if (output->crtc != crtc) - continue; - - drmmode_output = output->driver_private; - output_ids[output_count] = - drmmode_output->mode_output->connector_id; - output_count++; - } - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0) - if (!xf86CrtcRotate(crtc, mode, rotation)) - goto done; -#else - if (!xf86CrtcRotate(crtc)) - goto done; -#endif - -#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); -#endif - - drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); - - - fb_id = drmmode->fb_id; - if (drmmode_crtc->rotate_fb_id) { - fb_id = drmmode_crtc->rotate_fb_id; - x = 0; - y = 0; - } - ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - fb_id, x, y, output_ids, output_count, &kmode); - if (ret) - xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, - "failed to set mode: %s", strerror(-ret)); - else - ret = TRUE; - - /* Turn on any outputs on this crtc that may have been disabled */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - drmmode_output_dpms(output, DPMSModeOn); - } - - if (scrn->pScreen) - xf86_reload_cursors(scrn->pScreen); -done: - if (!ret) { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->rotation = saved_rotation; - crtc->mode = saved_mode; - } - return ret; -} - -static void -drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) -{ - -} - -static void -drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - - drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); -} - -static void -drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - ScrnInfoPtr scrn = crtc->scrn; - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - GCPtr gc; - - if (drmmode_crtc->cursor == NULL) - { - drmmode_crtc->cursor = calloc(1, sizeof(*drmmode_crtc->cursor)); - if (drmmode_crtc->cursor == NULL) { - ErrorF("Failed to allocate cursor.\n"); - return; - } - if (!glamor_create_cursor(scrn, drmmode_crtc->cursor, 64, 64)) { - free(drmmode_crtc->cursor); - drmmode_crtc->cursor = NULL; - ErrorF("Failed to create glamor cursor.\n"); - return; - } - } - - gc = GetScratchGC (drmmode_crtc->cursor->cursor_pixmap->drawable.depth, screen); - if (!gc) - return; - - ValidateGC (&drmmode_crtc->cursor->cursor_pixmap->drawable, gc); - (*gc->ops->PutImage)(&drmmode_crtc->cursor->cursor_pixmap->drawable, gc, - 32, 0, 0, 64, 64, 0, ZPixmap, (char*)image); - FreeScratchGC (gc); -} - - -static void -drmmode_hide_cursor (xf86CrtcPtr crtc) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - - drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - 0, 64, 64); -} - - -static void -_drmmode_destroy_cursor(xf86CrtcPtr crtc) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - - if (drmmode_crtc->cursor == NULL) - return; - drmmode_hide_cursor(crtc); - glamor_destroy_cursor(crtc->scrn, drmmode_crtc->cursor); - free(drmmode_crtc->cursor); - drmmode_crtc->cursor = NULL; -} - -static void -drmmode_destroy_cursor(ScrnInfoPtr scrn) -{ - int i; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - - for (i = 0; i < xf86_config->num_crtc; i++) - _drmmode_destroy_cursor(xf86_config->crtc[i]); -} - - - - -static void -drmmode_show_cursor (xf86CrtcPtr crtc) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - uint32_t handle, stride; - - ErrorF("show cursor\n"); - glamor_cursor_handle(drmmode_crtc->cursor, &handle, &stride); - - drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - handle, 64, 64); -} - -#if 0 -static void * -drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) -{ - ScrnInfoPtr scrn = crtc->scrn; - intel_screen_private *intel = intel_get_screen_private(scrn); - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - int size, ret; - unsigned long rotate_pitch; - - width = i830_pad_drawable_width(width, drmmode->cpp); - rotate_pitch = width * drmmode->cpp; - size = rotate_pitch * height; - - drmmode_crtc->rotate_bo = - drm_intel_bo_alloc(intel->bufmgr, "rotate", size, 4096); - - if (!drmmode_crtc->rotate_bo) { - xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow memory for rotated CRTC\n"); - return NULL; - } - - drm_intel_bo_disable_reuse(drmmode_crtc->rotate_bo); - - ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, - crtc->scrn->bitsPerPixel, rotate_pitch, - drmmode_crtc->rotate_bo->handle, - &drmmode_crtc->rotate_fb_id); - if (ret) { - ErrorF("failed to add rotate fb\n"); - drm_intel_bo_unreference(drmmode_crtc->rotate_bo); - return NULL; - } - - return drmmode_crtc->rotate_bo; -} - -static PixmapPtr -drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) -{ - ScrnInfoPtr scrn = crtc->scrn; - intel_screen_private *intel = intel_get_screen_private(scrn); - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - unsigned long rotate_pitch; - PixmapPtr rotate_pixmap; - - if (!data) { - data = drmmode_crtc_shadow_allocate (crtc, width, height); - if (!data) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - return NULL; - } - } - - rotate_pitch = - i830_pad_drawable_width(width, drmmode->cpp) * drmmode->cpp; - rotate_pixmap = GetScratchPixmapHeader(scrn->pScreen, - width, height, - scrn->depth, - scrn->bitsPerPixel, - rotate_pitch, - NULL); - - if (rotate_pixmap == NULL) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - return NULL; - } - - if (drmmode_crtc->rotate_bo) - i830_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo); - - intel->shadow_present = TRUE; - - return rotate_pixmap; -} - -static void -drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) -{ -} -#endif - -static void -drmmode_crtc_gamma_set(xf86CrtcPtr crtc, - CARD16 *red, CARD16 *green, CARD16 *blue, int size) -{ - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - - drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - size, red, green, blue); -} -static void -drmmode_crtc_destroy(xf86CrtcPtr crtc) -{ - ScrnInfoPtr scrn = crtc->scrn; - _drmmode_destroy_cursor(crtc); - crtc->driver_private = NULL; -} - -static const xf86CrtcFuncsRec drmmode_crtc_funcs = { - .dpms = drmmode_crtc_dpms, - .set_mode_major = drmmode_set_mode_major, - .set_cursor_colors = drmmode_set_cursor_colors, - .set_cursor_position = drmmode_set_cursor_position, - .show_cursor = drmmode_show_cursor, - .hide_cursor = drmmode_hide_cursor, - .load_cursor_argb = drmmode_load_cursor_argb, - .load_cursor_image = NULL, -#if 0 - .shadow_create = drmmode_crtc_shadow_create, - .shadow_allocate = drmmode_crtc_shadow_allocate, - .shadow_destroy = drmmode_crtc_shadow_destroy, -#endif - .gamma_set = drmmode_crtc_gamma_set, - .destroy = drmmode_crtc_destroy -}; - - -static void -drmmode_crtc_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) -{ - xf86CrtcPtr crtc; - drmmode_crtc_private_ptr drmmode_crtc; - - crtc = xf86CrtcCreate(scrn, &drmmode_crtc_funcs); - if (crtc == NULL) - return; - - drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); - drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, - drmmode->mode_res->crtcs[num]); - drmmode_crtc->drmmode = drmmode; - crtc->driver_private = drmmode_crtc; - - return; -} - -static xf86OutputStatus -drmmode_output_detect(xf86OutputPtr output) -{ - /* go to the hw and retrieve a new output struct */ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmmode_ptr drmmode = drmmode_output->drmmode; - xf86OutputStatus status; - drmModeFreeConnector(drmmode_output->mode_output); - - drmmode_output->mode_output = - drmModeGetConnector(drmmode->fd, drmmode_output->output_id); - - switch (drmmode_output->mode_output->connection) { - case DRM_MODE_CONNECTED: - status = XF86OutputStatusConnected; - break; - case DRM_MODE_DISCONNECTED: - status = XF86OutputStatusDisconnected; - break; - default: - case DRM_MODE_UNKNOWNCONNECTION: - status = XF86OutputStatusUnknown; - break; - } - return status; -} - -static Bool -drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr koutput = drmmode_output->mode_output; - struct fixed_panel_lvds *p_lvds = drmmode_output->private_data; - - /* - * If the connector type is LVDS, we will use the panel limit to - * verfiy whether the mode is valid. - */ - if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) { - if (pModes->HDisplay > p_lvds->hdisplay || - pModes->VDisplay > p_lvds->vdisplay) - return MODE_PANEL; - else - return MODE_OK; - } - return MODE_OK; -} - -static void fill_detailed_lvds_block(struct detailed_monitor_section *det_mon, - DisplayModePtr mode) -{ - struct detailed_timings *timing = &det_mon->section.d_timings; - - det_mon->type = DT; - timing->clock = mode->Clock * 1000; - timing->h_active = mode->HDisplay; - timing->h_blanking = mode->HTotal - mode->HDisplay; - timing->v_active = mode->VDisplay; - timing->v_blanking = mode->VTotal - mode->VDisplay; - timing->h_sync_off = mode->HSyncStart - mode->HDisplay; - timing->h_sync_width = mode->HSyncEnd - mode->HSyncStart; - timing->v_sync_off = mode->VSyncStart - mode->VDisplay; - timing->v_sync_width = mode->VSyncEnd - mode->VSyncStart; - - if (mode->Flags & V_PVSYNC) - timing->misc |= 0x02; - - if (mode->Flags & V_PHSYNC) - timing->misc |= 0x01; -} - -static int drmmode_output_lvds_edid(xf86OutputPtr output, - struct fixed_panel_lvds *p_lvds) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr koutput = drmmode_output->mode_output; - int i, j; - DisplayModePtr pmode; - xf86MonPtr edid_mon; - drmModeModeInfo *mode_ptr; - struct detailed_monitor_section *det_mon; - - if (output->MonInfo) { - /* - * If there exists the EDID, we will either find a DS_RANGES - * or replace a DS_VENDOR block, smashing it into a DS_RANGES - * block with opern refresh to match all the default modes. - */ - int edid_det_block_num; - edid_mon = output->MonInfo; - edid_mon->features.msc |= 0x01; - j = -1; - edid_det_block_num = sizeof(edid_mon->det_mon) / - sizeof(edid_mon->det_mon[0]); - for (i = 0; i < edid_det_block_num; i++) { - if (edid_mon->det_mon[i].type >= DS_VENDOR && j == -1) - j = i; - if (edid_mon->det_mon[i].type == DS_RANGES) { - j = i; - break; - } - } - if (j != -1) { - struct monitor_ranges *ranges = - &edid_mon->det_mon[j].section.ranges; - edid_mon->det_mon[j].type = DS_RANGES; - ranges->min_v = 0; - ranges->max_v = 200; - ranges->min_h = 0; - ranges->max_h = 200; - } - return 0; - } - /* - * If there is no EDID, we will construct a bogus EDID for LVDS output - * device. This is similar to what we have done in i830_lvds.c - */ - edid_mon = NULL; - edid_mon = calloc(1, sizeof(xf86Monitor)); - if (!edid_mon) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "Can't allocate memory for edid_mon.\n"); - return 0; - } - /* Find the fixed panel mode. - * In theory when there is no EDID, KMS kernel will return only one - * mode. And this can be regarded as fixed lvds panel mode. - * But it will be better to traverse the mode list to get the fixed - * lvds panel mode again as we don't know whether some new modes - * are added for the LVDS output device - */ - j = 0; - for (i = 0; i < koutput->count_modes; i++) { - mode_ptr = &koutput->modes[i]; - if ((mode_ptr->hdisplay == p_lvds->hdisplay) && - (mode_ptr->vdisplay == p_lvds->vdisplay)) { - /* find the fixed panel mode */ - j = i; - break; - } - } - pmode = xnfalloc(sizeof(DisplayModeRec)); - drmmode_ConvertFromKMode(output->scrn, &koutput->modes[j], pmode); - /*support DPM, instead of DPMS*/ - edid_mon->features.dpms |= 0x1; - /*defaultly support RGB color display*/ - edid_mon->features.display_type |= 0x1; - /*defaultly display support continuous-freqencey*/ - edid_mon->features.msc |= 0x1; - /*defaultly the EDID version is 1.4 */ - edid_mon->ver.version = 1; - edid_mon->ver.revision = 4; - det_mon = edid_mon->det_mon; - if (pmode) { - /* now we construct new EDID monitor, - * so filled one detailed timing block - */ - fill_detailed_lvds_block(det_mon, pmode); - /* the filed timing block should be set preferred*/ - edid_mon->features.msc |= 0x2; - det_mon = det_mon + 1; - } - /* Set wide sync ranges so we get all modes - * handed to valid_mode for checking - */ - det_mon->type = DS_RANGES; - det_mon->section.ranges.min_v = 0; - det_mon->section.ranges.max_v = 200; - det_mon->section.ranges.min_h = 0; - det_mon->section.ranges.max_h = 200; - output->MonInfo = edid_mon; - return 0; -} - -static DisplayModePtr -drmmode_output_get_modes(xf86OutputPtr output) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr koutput = drmmode_output->mode_output; - drmmode_ptr drmmode = drmmode_output->drmmode; - int i; - DisplayModePtr Modes = NULL, Mode; - drmModePropertyPtr props; - struct fixed_panel_lvds *p_lvds; - drmModeModeInfo *mode_ptr; - - /* look for an EDID property */ - for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(drmmode->fd, koutput->props[i]); - if (!props) - continue; - if (!(props->flags & DRM_MODE_PROP_BLOB)) { - drmModeFreeProperty(props); - continue; - } - - if (!strcmp(props->name, "EDID")) { - drmModeFreePropertyBlob(drmmode_output->edid_blob); - drmmode_output->edid_blob = - drmModeGetPropertyBlob(drmmode->fd, - koutput->prop_values[i]); - } - drmModeFreeProperty(props); - } - - if (drmmode_output->edid_blob) - xf86OutputSetEDID(output, - xf86InterpretEDID(output->scrn->scrnIndex, - drmmode_output->edid_blob->data)); - else - xf86OutputSetEDID(output, - xf86InterpretEDID(output->scrn->scrnIndex, - NULL)); - - /* modes should already be available */ - for (i = 0; i < koutput->count_modes; i++) { - Mode = xnfalloc(sizeof(DisplayModeRec)); - - drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], - Mode); - Modes = xf86ModesAdd(Modes, Mode); - - } - p_lvds = drmmode_output->private_data; - /* - * If the connector type is LVDS, we will traverse the kernel mode to - * get the panel limit. - * If it is incorrect, please fix me. - */ - if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) { - p_lvds->hdisplay = 0; - p_lvds->vdisplay = 0; - for (i = 0; i < koutput->count_modes; i++) { - mode_ptr = &koutput->modes[i]; - if ((mode_ptr->hdisplay >= p_lvds->hdisplay) && - (mode_ptr->vdisplay >= p_lvds->vdisplay)) { - p_lvds->hdisplay = mode_ptr->hdisplay; - p_lvds->vdisplay = mode_ptr->vdisplay; - } - } - if (!p_lvds->hdisplay || !p_lvds->vdisplay) - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "Incorrect KMS mode.\n"); - drmmode_output_lvds_edid(output, p_lvds); - } - return Modes; -} - -static void -drmmode_output_destroy(xf86OutputPtr output) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - int i; - - if (drmmode_output->edid_blob) - drmModeFreePropertyBlob(drmmode_output->edid_blob); - for (i = 0; i < drmmode_output->num_props; i++) { - drmModeFreeProperty(drmmode_output->props[i].mode_prop); - free(drmmode_output->props[i].atoms); - } - free(drmmode_output->props); - drmModeFreeConnector(drmmode_output->mode_output); - if (drmmode_output->private_data) { - free(drmmode_output->private_data); - drmmode_output->private_data = NULL; - } - if (drmmode_output->backlight_iface) - drmmode_backlight_set(output, drmmode_output->backlight_active_level); - free(drmmode_output); - output->driver_private = NULL; -} - -static void -drmmode_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - - if (!drmmode_output->backlight_iface) - return; - - if (mode == DPMSModeOn) { - /* If we're going from off->on we may need to turn on the backlight. */ - if (oldmode != DPMSModeOn) - drmmode_backlight_set(output, drmmode_output->backlight_active_level); - } else { - /* Only save the current backlight value if we're going from on to off. */ - if (oldmode == DPMSModeOn) - drmmode_output->backlight_active_level = drmmode_backlight_get(output); - drmmode_backlight_set(output, 0); - } -} - -static void -drmmode_output_dpms(xf86OutputPtr output, int mode) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr koutput = drmmode_output->mode_output; - drmmode_ptr drmmode = drmmode_output->drmmode; - int i; - drmModePropertyPtr props; - - for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(drmmode->fd, koutput->props[i]); - if (!props) - continue; - - if (!strcmp(props->name, "DPMS")) { - drmModeConnectorSetProperty(drmmode->fd, - drmmode_output->output_id, - props->prop_id, - mode); - drmmode_output_dpms_backlight(output, - drmmode_output->dpms_mode, - mode); - drmmode_output->dpms_mode = mode; - drmModeFreeProperty(props); - return; - } - drmModeFreeProperty(props); - } -} - -static Bool -drmmode_property_ignore(drmModePropertyPtr prop) -{ - if (!prop) - return TRUE; - /* ignore blob prop */ - if (prop->flags & DRM_MODE_PROP_BLOB) - return TRUE; - /* ignore standard property */ - if (!strcmp(prop->name, "EDID") || - !strcmp(prop->name, "DPMS")) - return TRUE; - - return FALSE; -} - -#define BACKLIGHT_NAME "Backlight" -#define BACKLIGHT_DEPRECATED_NAME "BACKLIGHT" -static Atom backlight_atom, backlight_deprecated_atom; - -static void -drmmode_output_create_resources(xf86OutputPtr output) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr mode_output = drmmode_output->mode_output; - drmmode_ptr drmmode = drmmode_output->drmmode; - drmModePropertyPtr drmmode_prop; - int i, j, err; - - drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec)); - if (!drmmode_output->props) - return; - - drmmode_output->num_props = 0; - for (i = 0, j = 0; i < mode_output->count_props; i++) { - drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]); - if (drmmode_property_ignore(drmmode_prop)) { - drmModeFreeProperty(drmmode_prop); - continue; - } - drmmode_output->props[j].mode_prop = drmmode_prop; - drmmode_output->props[j].value = mode_output->prop_values[i]; - drmmode_output->num_props++; - j++; - } - - for (i = 0; i < drmmode_output->num_props; i++) { - drmmode_prop_ptr p = &drmmode_output->props[i]; - drmmode_prop = p->mode_prop; - - if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { - INT32 range[2]; - - p->num_atoms = 1; - p->atoms = calloc(p->num_atoms, sizeof(Atom)); - if (!p->atoms) - continue; - p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); - range[0] = drmmode_prop->values[0]; - range[1] = drmmode_prop->values[1]; - err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], - FALSE, TRUE, - drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, - 2, range); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", err); - } - err = RRChangeOutputProperty(output->randr_output, p->atoms[0], - XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - } - } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { - p->num_atoms = drmmode_prop->count_enums + 1; - p->atoms = calloc(p->num_atoms, sizeof(Atom)); - if (!p->atoms) - continue; - p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); - for (j = 1; j <= drmmode_prop->count_enums; j++) { - struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; - p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); - } - err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], - FALSE, FALSE, - drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, - p->num_atoms - 1, (INT32 *)&p->atoms[1]); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", err); - } - for (j = 0; j < drmmode_prop->count_enums; j++) - if (drmmode_prop->enums[j].value == p->value) - break; - /* there's always a matching value */ - err = RRChangeOutputProperty(output->randr_output, p->atoms[0], - XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - } - } - } - - if (drmmode_output->backlight_iface) { - INT32 data, backlight_range[2]; - /* Set up the backlight property, which takes effect immediately - * and accepts values only within the backlight_range. */ - backlight_atom = MakeAtom(BACKLIGHT_NAME, sizeof(BACKLIGHT_NAME) - 1, TRUE); - backlight_deprecated_atom = MakeAtom(BACKLIGHT_DEPRECATED_NAME, - sizeof(BACKLIGHT_DEPRECATED_NAME) - 1, TRUE); - - backlight_range[0] = 0; - backlight_range[1] = drmmode_output->backlight_max; - err = RRConfigureOutputProperty(output->randr_output, backlight_atom, - FALSE, TRUE, FALSE, 2, backlight_range); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", err); - } - err = RRConfigureOutputProperty(output->randr_output, backlight_deprecated_atom, - FALSE, TRUE, FALSE, 2, backlight_range); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", err); - } - /* Set the current value of the backlight property */ - data = drmmode_output->backlight_active_level; - err = RRChangeOutputProperty(output->randr_output, backlight_atom, - XA_INTEGER, 32, PropModeReplace, 1, &data, - FALSE, TRUE); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - } - err = RRChangeOutputProperty(output->randr_output, backlight_deprecated_atom, - XA_INTEGER, 32, PropModeReplace, 1, &data, - FALSE, TRUE); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - } - } -} - -static Bool -drmmode_output_set_property(xf86OutputPtr output, Atom property, - RRPropertyValuePtr value) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmmode_ptr drmmode = drmmode_output->drmmode; - int i; - - if (property == backlight_atom || property == backlight_deprecated_atom) { - INT32 val; - - if (value->type != XA_INTEGER || value->format != 32 || - value->size != 1) - { - return FALSE; - } - - val = *(INT32 *)value->data; - if (val < 0 || val > drmmode_output->backlight_max) - return FALSE; - - if (drmmode_output->dpms_mode == DPMSModeOn) - drmmode_backlight_set(output, val); - drmmode_output->backlight_active_level = val; - return TRUE; - } - - for (i = 0; i < drmmode_output->num_props; i++) { - drmmode_prop_ptr p = &drmmode_output->props[i]; - - if (p->atoms[0] != property) - continue; - - if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { - uint32_t val; - - if (value->type != XA_INTEGER || value->format != 32 || - value->size != 1) - return FALSE; - val = *(uint32_t *)value->data; - - drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, - p->mode_prop->prop_id, (uint64_t)val); - return TRUE; - } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { - Atom atom; - const char *name; - int j; - - if (value->type != XA_ATOM || value->format != 32 || value->size != 1) - return FALSE; - memcpy(&atom, value->data, 4); - name = NameForAtom(atom); - - /* search for matching name string, then set its value down */ - for (j = 0; j < p->mode_prop->count_enums; j++) { - if (!strcmp(p->mode_prop->enums[j].name, name)) { - drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, - p->mode_prop->prop_id, p->mode_prop->enums[j].value); - return TRUE; - } - } - return FALSE; - } - } - - return TRUE; -} - -static Bool -drmmode_output_get_property(xf86OutputPtr output, Atom property) -{ - drmmode_output_private_ptr drmmode_output = output->driver_private; - int err; - - if (property == backlight_atom || property == backlight_deprecated_atom) { - INT32 val; - - if (! drmmode_output->backlight_iface) - return FALSE; - - val = drmmode_backlight_get(output); - if (val < 0) - return FALSE; - err = RRChangeOutputProperty(output->randr_output, property, - XA_INTEGER, 32, PropModeReplace, 1, &val, - FALSE, TRUE); - if (err != 0) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", err); - return FALSE; - } - - return TRUE; - } - - return TRUE; -} - -static const xf86OutputFuncsRec drmmode_output_funcs = { - .create_resources = drmmode_output_create_resources, -#ifdef RANDR_12_INTERFACE - .set_property = drmmode_output_set_property, - .get_property = drmmode_output_get_property, -#endif - .dpms = drmmode_output_dpms, - .detect = drmmode_output_detect, - .mode_valid = drmmode_output_mode_valid, - - .get_modes = drmmode_output_get_modes, - .destroy = drmmode_output_destroy -}; - -static int subpixel_conv_table[7] = { 0, SubPixelUnknown, - SubPixelHorizontalRGB, - SubPixelHorizontalBGR, - SubPixelVerticalRGB, - SubPixelVerticalBGR, - SubPixelNone }; - -static const char *output_names[] = { "None", - "VGA", - "DVI", - "DVI", - "DVI", - "Composite", - "TV", - "LVDS", - "CTV", - "DIN", - "DP", - "HDMI", - "HDMI", -}; - - -static void -drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num) -{ - xf86OutputPtr output; - drmModeConnectorPtr koutput; - drmModeEncoderPtr kencoder; - drmmode_output_private_ptr drmmode_output; - char name[32]; - - koutput = drmModeGetConnector(drmmode->fd, - drmmode->mode_res->connectors[num]); - if (!koutput) - return; - - kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]); - if (!kencoder) { - drmModeFreeConnector(koutput); - return; - } - - snprintf(name, 32, "%s%d", output_names[koutput->connector_type], - koutput->connector_type_id); - - output = xf86OutputCreate (scrn, &drmmode_output_funcs, name); - if (!output) { - drmModeFreeEncoder(kencoder); - drmModeFreeConnector(koutput); - return; - } - - drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); - if (!drmmode_output) { - xf86OutputDestroy(output); - drmModeFreeConnector(koutput); - drmModeFreeEncoder(kencoder); - return; - } - /* - * If the connector type of the output device is LVDS, we will - * allocate the private_data to store the panel limit. - * For example: hdisplay, vdisplay - */ - drmmode_output->private_data = NULL; - if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) { - drmmode_output->private_data = calloc( - sizeof(struct fixed_panel_lvds), 1); - if (!drmmode_output->private_data) - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Can't allocate private memory for LVDS.\n"); - } - drmmode_output->output_id = drmmode->mode_res->connectors[num]; - drmmode_output->mode_output = koutput; - drmmode_output->mode_encoder = kencoder; - drmmode_output->drmmode = drmmode; - output->mm_width = koutput->mmWidth; - output->mm_height = koutput->mmHeight; - - output->subpixel_order = subpixel_conv_table[koutput->subpixel]; - output->driver_private = drmmode_output; - - if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) - drmmode_backlight_init(output); - - output->possible_crtcs = kencoder->possible_crtcs; - output->possible_clones = kencoder->possible_clones; - return; -} - - -static Bool -drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - - if (!drmmode_update_fb(scrn, width, height)) - return FALSE; - for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - - if (!crtc->enabled) - continue; - drmmode_set_mode_major(crtc, &crtc->mode, - crtc->rotation, crtc->x, crtc->y); - } - - return TRUE; -} - -static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { - drmmode_xf86crtc_resize -}; - -#if 0 -Bool -drmmode_do_pageflip(ScreenPtr screen, dri_bo *new_front, dri_bo *old_front, - void *data) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - intel_screen_private *intel = intel_get_screen_private(scrn); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - unsigned int pitch = scrn->displayWidth * intel->cpp; - int i, old_fb_id; - unsigned int crtc_id; - - /* - * Create a new handle for the back buffer - */ - old_fb_id = drmmode->fb_id; - if (drmModeAddFB(drmmode->fd, scrn->virtualX, scrn->virtualY, - scrn->depth, scrn->bitsPerPixel, pitch, - new_front->handle, &drmmode->fb_id)) - goto error_out; - - /* - * Queue flips on all enabled CRTCs - * Note that if/when we get per-CRTC buffers, we'll have to update this. - * Right now it assumes a single shared fb across all CRTCs, with the - * kernel fixing up the offset of each CRTC as necessary. - * - * Also, flips queued on disabled or incorrectly configured displays - * may never complete; this is a configuration error. - */ - for (i = 0; i < config->num_crtc; i++) { - xf86CrtcPtr crtc = config->crtc[i]; - - if (!crtc->enabled) - continue; - - drmmode_crtc = crtc->driver_private; - crtc_id = drmmode_crtc->mode_crtc->crtc_id; - drmmode->event_data = data; - drmmode->flip_count++; - if (drmModePageFlip(drmmode->fd, crtc_id, drmmode->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, drmmode)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "flip queue failed: %s\n", strerror(errno)); - goto error_undo; - } - } - - dri_bo_pin(new_front, 0); - dri_bo_unpin(new_front); - - scrn->fbOffset = new_front->offset; - intel->front_buffer->bo = new_front; - intel->front_buffer->offset = new_front->offset; - drmmode->old_fb_id = old_fb_id; - - return TRUE; - -error_undo: - drmModeRmFB(drmmode->fd, drmmode->fb_id); - drmmode->fb_id = old_fb_id; - -error_out: - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", - strerror(errno)); - return FALSE; -} - -static void -drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event_data); -} - -static void -drmmode_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - drmmode_ptr drmmode = event_data; - - drmmode->flip_count--; - if (drmmode->flip_count > 0) - return; - - drmModeRmFB(drmmode->fd, drmmode->old_fb_id); - - I830DRI2FlipEventHandler(frame, tv_sec, tv_usec, drmmode->event_data); -} - -static void -drm_wakeup_handler(pointer data, int err, pointer p) -{ - drmmode_ptr drmmode = data; - fd_set *read_mask = p; - - if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) - drmHandleEvent(drmmode->fd, &drmmode->event_context); -} -#endif - -Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp) -{ - drmmode_ptr drmmode; - unsigned int i; - - drmmode = xnfalloc(sizeof *drmmode); - drmmode->fd = fd; - drmmode->fb_id = 0; - - xf86CrtcConfigInit(scrn, &drmmode_xf86crtc_config_funcs); - - drmmode->cpp = cpp; - drmmode->mode_res = drmModeGetResources(drmmode->fd); - if (!drmmode->mode_res) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "failed to get resources: %s\n", strerror(errno)); - return FALSE; - } - - xf86CrtcSetSizeRange(scrn, 320, 200, drmmode->mode_res->max_width, - drmmode->mode_res->max_height); - for (i = 0; i < drmmode->mode_res->count_crtcs; i++) - drmmode_crtc_init(scrn, drmmode, i); - - for (i = 0; i < drmmode->mode_res->count_connectors; i++) - drmmode_output_init(scrn, drmmode, i); - - xf86InitialConfiguration(scrn, TRUE); - -#if 0 - gp.param = I915_PARAM_HAS_PAGEFLIPPING; - gp.value = &has_flipping; - (void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, - sizeof(gp)); - if (has_flipping) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Kernel page flipping support detected, enabling\n"); - intel->use_pageflipping = TRUE; - drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; - drmmode->event_context.vblank_handler = drmmode_vblank_handler; - drmmode->event_context.page_flip_handler = - drmmode_page_flip_handler; - AddGeneralSocket(fd); - RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - drm_wakeup_handler, drmmode); - } -#endif - - return TRUE; -} - -void drmmode_closefb(ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr xf86_config; - drmmode_crtc_private_ptr drmmode_crtc; - drmmode_ptr drmmode; - - xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - - drmmode_crtc = xf86_config->crtc[0]->driver_private; - drmmode = drmmode_crtc->drmmode; - - drmmode_destroy_cursor(scrn); - - drmModeRmFB(drmmode->fd, drmmode->fb_id); - drmmode->fb_id = 0; -} diff --git a/hw/xfree86/glamor/glamor_ddx.c b/hw/xfree86/glamor/glamor_ddx.c deleted file mode 100644 index f4b37ab6b..000000000 --- a/hw/xfree86/glamor/glamor_ddx.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including - * the next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Kristian Høgsberg - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include - -#include "../../../mi/micmap.h" -#include -#include -//#define GC XORG_GC -#include -//#undef GC - -#include "glamor_ddx.h" - -#define GLAMOR_VERSION_MAJOR 0 -#define GLAMOR_VERSION_MINOR 1 -#define GLAMOR_VERSION_PATCH 0 - -static const char glamor_ddx_name[] = "glamor"; - -static void -glamor_ddx_identify(int flags) -{ - xf86Msg(X_INFO, "Standalone %s: OpenGL accelerated X.org driver\n", glamor_ddx_name); -} - -static Bool -glamor_ddx_init_front_buffer(ScrnInfoPtr scrn, int width, int height) -{ - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - - glamor->root_bo = gbm_bo_create(glamor->gbm, width, height, - GBM_BO_FORMAT_ARGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - - if (glamor->root_bo == NULL) - return FALSE; - - scrn->virtualX = width; - scrn->virtualY = height; - /* XXX shall we update displayWidth here ? */ - return TRUE; -} - -static Bool -glamor_create_screen_image(ScrnInfoPtr scrn) -{ - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - unsigned int handle, stride; - handle = gbm_bo_get_handle(glamor->root_bo).u32; - stride = gbm_bo_get_pitch(glamor->root_bo); - return glamor_create_egl_screen_image(screen, handle, stride); -} - -Bool -glamor_front_buffer_resize(ScrnInfoPtr scrn, int width, int height) -{ - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - - if (glamor->root_bo != NULL) { - glamor_close_egl_screen(screen); - gbm_bo_destroy(glamor->root_bo); - glamor->root_bo = NULL; - } - - if (!glamor_ddx_init_front_buffer(scrn, width, height)) - return FALSE; - return glamor_create_screen_image(scrn); -} - -void -glamor_frontbuffer_handle(ScrnInfoPtr scrn, uint32_t *handle, uint32_t *pitch) -{ - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - *handle = gbm_bo_get_handle(glamor->root_bo).u32; - *pitch = gbm_bo_get_pitch(glamor->root_bo); -} - -Bool -glamor_create_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor, int width, int height) -{ - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - unsigned int handle, stride; - - - if (cursor->cursor_pixmap) - glamor_destroy_cursor(scrn, cursor); - - cursor->cursor_pixmap = screen->CreatePixmap(screen, 0, 0, 32, 0); - if (cursor->cursor_pixmap == NULL) - return FALSE; - screen->ModifyPixmapHeader(cursor->cursor_pixmap, width, height, 0, 0, 0, 0); - cursor->cursor_bo = gbm_bo_create(glamor->gbm, width, height, - GBM_BO_FORMAT_ARGB8888, - GBM_BO_USE_SCANOUT - | GBM_BO_USE_RENDERING - | GBM_BO_USE_CURSOR_64X64); - - if (cursor->cursor_bo == NULL) - goto fail; - glamor_cursor_handle(cursor, &handle, &stride); - if (!glamor_create_egl_pixmap_image(cursor->cursor_pixmap, handle, stride)) - goto fail; - - return TRUE; - -fail: - glamor_destroy_cursor(scrn, cursor); - return FALSE; -} - -void glamor_destroy_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor) -{ - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - if (cursor->cursor_pixmap) - screen->DestroyPixmap(cursor->cursor_pixmap); - if (cursor->cursor_bo) - gbm_bo_destroy(cursor->cursor_bo); - cursor->cursor_bo = NULL; - cursor->cursor_pixmap = NULL; -} - -void -glamor_cursor_handle(struct glamor_gbm_cursor *cursor, uint32_t *handle, uint32_t *pitch) -{ - *handle = gbm_bo_get_handle(cursor->cursor_bo).u32; - *pitch = gbm_bo_get_pitch(cursor->cursor_bo); - ErrorF("cursor stride: %d\n", *pitch); -} - -char * dri_device_name = "/dev/dri/card0"; -static Bool -glamor_ddx_pre_init(ScrnInfoPtr scrn, int flags) -{ - struct glamor_ddx_screen_private *glamor; - rgb defaultWeight = { 0, 0, 0 }; - - glamor = xnfcalloc(sizeof *glamor, 1); - - scrn->driverPrivate = glamor; - glamor->fd = open(dri_device_name, O_RDWR); - if (glamor->fd == -1 ) { - ErrorF("Failed to open %s: %s\n", dri_device_name, strerror(errno)); - goto fail; - } - - glamor->cpp = 4; - - scrn->monitor = scrn->confScreen->monitor; - scrn->progClock = TRUE; - scrn->rgbBits = 8; - - if (!xf86SetDepthBpp(scrn, 0, 0, 0, Support32bppFb)) - goto fail; - - xf86PrintDepthBpp(scrn); - - if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) - goto fail; - if (!xf86SetDefaultVisual(scrn, -1)) - goto fail; - - glamor->cpp = scrn->bitsPerPixel / 8; - - if (drmmode_pre_init(scrn, glamor->fd, glamor->cpp) == FALSE) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Kernel modesetting setup failed\n"); - goto fail; - } - - scrn->currentMode = scrn->modes; - xf86SetDpi(scrn, 0, 0); - - /* Load the required sub modules */ - if (!xf86LoadSubModule(scrn, "fb")) - goto fail; - - if (!xf86LoadSubModule(scrn, "glamor_dix")) - goto fail; - - return TRUE; - -fail: - scrn->driverPrivate = NULL; - free(glamor); - return FALSE; -} - -static void -glamor_ddx_adjust_frame(int scrnIndex, int x, int y, int flags) -{ -} - -static Bool -glamor_ddx_enter_vt(int scrnIndex, int flags) -{ - ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - - if (drmSetMaster(glamor->fd)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmSetMaster failed: %s\n", strerror(errno)); - return FALSE; - } - if (!xf86SetDesiredModes(scrn)) - return FALSE; - return TRUE; -} - -static void -glamor_ddx_leave_vt(int scrnIndex, int flags) -{ - ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - - drmDropMaster(glamor->fd); -} - -static Bool -glamor_ddx_create_screen_resources(ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - - screen->CreateScreenResources = glamor->CreateScreenResources; - if (!(*screen->CreateScreenResources) (screen)) - return FALSE; - if (!glamor_glyphs_init(screen)) - return FALSE; - if (glamor->root_bo == NULL) - return FALSE; - if (!glamor_create_screen_image(scrn)) - return FALSE; - return TRUE; -} - -static Bool -glamor_ddx_close_screen(int scrnIndex, ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - - screen->CloseScreen = glamor->CloseScreen; - (*screen->CloseScreen) (scrnIndex, screen); - - if (scrn->vtSema == TRUE) - glamor_ddx_leave_vt(scrnIndex, 0); - - glamor_fini(screen); - glamor_close_egl_screen(screen); - gbm_bo_destroy(glamor->root_bo); - drmmode_closefb(scrn); - - return TRUE; -} - -static Bool -glamor_ddx_screen_init(int scrnIndex, ScreenPtr screen, int argc, char **argv) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - VisualPtr visual; - - glamor->gbm = gbm_create_device(glamor->fd); - if (glamor->gbm == NULL) { - ErrorF("couldn't create gbm device\n"); - return FALSE; - } - - glamor_egl_init(scrn, glamor->fd); - - miClearVisualTypes(); - if (!miSetVisualTypes(scrn->depth, - miGetDefaultVisualMask(scrn->depth), - scrn->rgbBits, scrn->defaultVisual)) - return FALSE; - if (!miSetPixmapDepths()) - return FALSE; - - if (!glamor_ddx_init_front_buffer(scrn, scrn->virtualX, scrn->virtualY)) - return FALSE; - - if (!fbScreenInit(screen, NULL, - scrn->virtualX, scrn->virtualY, - scrn->xDpi, scrn->yDpi, - 1, scrn->bitsPerPixel)) - return FALSE; - - if (scrn->bitsPerPixel > 8) { - /* Fixup RGB ordering */ - visual = screen->visuals + screen->numVisuals; - while(--visual >= screen->visuals) { - if ((visual->class | DynamicClass) == DirectColor) { - visual->offsetRed = scrn->offset.red; - visual->offsetGreen = scrn->offset.green; - visual->offsetBlue = scrn->offset.blue; - visual->redMask = scrn->mask.red; - visual->blueMask = scrn->mask.blue; - } - } - } - - fbPictureInit(screen, NULL, 0); - xf86SetBlackWhitePixels(screen); - - if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to initialize glamor\n"); - return FALSE; - } - - miInitializeBackingStore(screen); - xf86SetBackingStore(screen); - xf86SetSilkenMouse(screen); - miDCInitialize(screen, xf86GetPointerScreenFuncs()); - - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); - - if (!xf86_cursors_init(screen, 64, 64, - (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | - HARDWARE_CURSOR_INVERT_MASK | - HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | - HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED | - HARDWARE_CURSOR_UPDATE_UNHIDDEN | - HARDWARE_CURSOR_ARGB))) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Hardware cursor initialization failed\n"); - } - - /* Must force it before EnterVT, so we are in control of VT and - * later memory should be bound when allocating, e.g rotate_mem */ - scrn->vtSema = TRUE; - - if (!glamor_ddx_enter_vt(scrnIndex, 0)) - return FALSE; - - screen->SaveScreen = xf86SaveScreen; - glamor->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = glamor_ddx_create_screen_resources; - glamor->CloseScreen = screen->CloseScreen; - screen->CloseScreen = glamor_ddx_close_screen; - /* Fixme should we init crtc screen here? */ - if (!xf86CrtcScreenInit(screen)) - return FALSE; - if (!miCreateDefColormap(screen)) - return FALSE; - /* Fixme should we add handle colormap here? */ - - xf86DPMSInit(screen, xf86DPMSSet, 0); - - return TRUE; -} - -static void -glamor_ddx_free_screen(int scrnIndex, int flags) -{ - ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_ddx_screen_private *glamor = glamor_ddx_get_screen_private(scrn); - if (glamor != NULL) - { - close(glamor->fd); - free(glamor); - scrn->driverPrivate = NULL; - } -} - -static ModeStatus -glamor_ddx_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) -{ - if (mode->Flags & V_INTERLACE) { - if (verbose) { - xf86DrvMsg(scrnIndex, X_PROBED, - "Removing interlaced mode \"%s\"\n", - mode->name); - } - return MODE_BAD; - } - return MODE_OK; -} - -static Bool -glamor_ddx_probe(struct _DriverRec *drv, int flags) -{ - ScrnInfoPtr scrn = NULL; - GDevPtr *sections; - int entity, n; - - n = xf86MatchDevice(glamor_ddx_name, §ions); - if (n <= 0) - return FALSE; - - entity = xf86ClaimFbSlot(drv, 0, sections[0], TRUE); - - scrn = xf86ConfigFbEntity(scrn, 0, entity, NULL, NULL, NULL, NULL); - if (scrn == NULL) { - xf86Msg(X_ERROR, "Failed to add fb entity\n"); - return FALSE; - } - - scrn->driverVersion = 1; - scrn->driverName = (char *) glamor_ddx_name; - scrn->name = (char *) glamor_ddx_name; - scrn->Probe = NULL; - - scrn->PreInit = glamor_ddx_pre_init; - scrn->ScreenInit = glamor_ddx_screen_init; - scrn->AdjustFrame = glamor_ddx_adjust_frame; - scrn->EnterVT = glamor_ddx_enter_vt; - scrn->LeaveVT = glamor_ddx_leave_vt; - scrn->FreeScreen = glamor_ddx_free_screen; - scrn->ValidMode = glamor_ddx_valid_mode; - - return TRUE; -} - -static const OptionInfoRec * -glamor_ddx_available_options(int chipid, int busid) -{ - return NULL; -} - -static Bool -glamor_ddx_driver_func(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr) -{ - xorgHWFlags *flag; - - switch (op) { - case GET_REQUIRED_HW_INTERFACES: - flag = (CARD32*)ptr; - (*flag) = 0; - return TRUE; - default: - /* Unknown or deprecated function */ - return FALSE; - } -} - -_X_EXPORT DriverRec glamor_ddx = { - 1, - "glamor", - glamor_ddx_identify, - glamor_ddx_probe, - glamor_ddx_available_options, - NULL, - 0, - glamor_ddx_driver_func, -}; - -static pointer -glamor_ddx_setup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = 0; - - /* This module should be loaded only once, but check to be sure. - */ - if (!setupDone) { - setupDone = 1; - xf86AddDriver(&glamor_ddx, module, HaveDriverFuncs); - - /* - * The return value must be non-NULL on success even though there - * is no TearDownProc. - */ - return (pointer) 1; - } else { - if (errmaj) - *errmaj = LDR_ONCEONLY; - return NULL; - } -} - -static XF86ModuleVersionInfo glamor_ddx_version_info = { - glamor_ddx_name, - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - GLAMOR_VERSION_MAJOR, - GLAMOR_VERSION_MINOR, - GLAMOR_VERSION_PATCH, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - {0, 0, 0, 0} -}; - -_X_EXPORT XF86ModuleData glamorModuleData = { - &glamor_ddx_version_info, - glamor_ddx_setup, - NULL -}; diff --git a/hw/xfree86/glamor/glamor_ddx.h b/hw/xfree86/glamor/glamor_ddx.h deleted file mode 100644 index 3ffd48852..000000000 --- a/hw/xfree86/glamor/glamor_ddx.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef GLAMOR_DDX_H -#define GLAMOR_DDX_H - -#include -#define GLAMOR_FOR_XORG 1 -#include -struct glamor_ddx_screen_private { - struct gbm_bo *root_bo; - struct gbm_bo *cursor_bo; - struct gbm_device *gbm; - - CreateScreenResourcesProcPtr CreateScreenResources; - CloseScreenProcPtr CloseScreen; - int fd; - int cpp; -}; - -struct glamor_gbm_cursor { - struct gbm_bo *cursor_bo; - PixmapPtr cursor_pixmap; -}; - -inline static struct glamor_ddx_screen_private * -glamor_ddx_get_screen_private(ScrnInfoPtr scrn) -{ - return (struct glamor_ddx_screen_private *) (scrn->driverPrivate); -} - -Bool glamor_front_buffer_resize(ScrnInfoPtr scrn, int width, int height); -void glamor_frontbuffer_handle(ScrnInfoPtr scrn, - uint32_t *handle, uint32_t *pitch); -Bool glamor_load_cursor(ScrnInfoPtr scrn, - int width, int height); - -void glamor_cursor_handle(struct glamor_gbm_cursor *cursor, uint32_t *handle, uint32_t *pitch); -Bool glamor_create_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor, int width, int height); -void glamor_destroy_cursor(ScrnInfoPtr scrn, struct glamor_gbm_cursor *cursor) ; - -Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp); -void drmmode_closefb(ScrnInfoPtr scrn); - -#endif diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in index c9760b090..0d1ea9142 100644 --- a/include/xorg-config.h.in +++ b/include/xorg-config.h.in @@ -139,15 +139,4 @@ /* Build with libdrm support */ #undef WITH_LIBDRM - -/* Build GLAMOR */ -#undef GLAMOR - -/* Build GLAMOR over GLES2*/ -#undef GLAMOR_GLES2 - -/* Build GLAMOR ddx*/ -#undef GLAMOR_DDX - - #endif /* _XORG_CONFIG_H_ */ From b861aad8e2fcf6fe1fae4f26abb650bb4eb499c6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 2 Nov 2011 13:44:50 +0800 Subject: [PATCH 226/462] Initial version. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 27 +- glamor/glamor.c | 537 ++++---- glamor/glamor.h | 40 +- glamor/glamor_copyarea.c | 657 +++++----- glamor/glamor_copywindow.c | 36 +- glamor/glamor_core.c | 699 +++++----- glamor/glamor_debug.h | 7 +- glamor/glamor_egl.c | 371 +++--- glamor/glamor_eglmodule.c | 44 + glamor/glamor_fill.c | 285 ++-- glamor/glamor_fillspans.c | 86 +- glamor/glamor_getspans.c | 134 +- glamor/glamor_gl_dispatch.c | 124 +- glamor/glamor_gl_dispatch.h | 194 +-- glamor/glamor_glyphs.c | 1187 +++++++++-------- glamor/glamor_picture.c | 89 +- glamor/glamor_pixmap.c | 1133 ++++++++-------- glamor/glamor_pixmap.indent.c | 821 ++++++++++++ glamor/glamor_polyfillrect.c | 127 +- glamor/glamor_polylines.c | 248 ++-- glamor/glamor_priv.h | 414 +++--- glamor/glamor_putimage.c | 588 ++++----- glamor/glamor_render.c | 2317 +++++++++++++++++---------------- glamor/glamor_setspans.c | 134 +- glamor/glamor_tile.c | 275 ++-- glamor/glamor_triangles.c | 37 +- glamor/glamor_utils.h | 599 ++++----- glamor/glamor_window.c | 57 +- 28 files changed, 6256 insertions(+), 5011 deletions(-) create mode 100644 glamor/glamor_eglmodule.c create mode 100644 glamor/glamor_pixmap.indent.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 8712e765a..a382eb5ce 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -1,29 +1,24 @@ -noinst_LTLIBRARIES = libglamor.la +inst_LTLIBRARIES = libglamor.la # Override these since glamor doesn't need them and the needed files aren't # built (in hw/xfree86/os-support/solaris) until after glamor is built SOLARIS_ASM_CFLAGS="" -if XORG -sdk_HEADERS = glamor.h -endif - if GLAMOR_GLES2 libglamor_la_LIBADD = $(GLESV2_LIBS) else libglamor_la_LIBADD = $(GL_LIBS) endif -if XORG -sdk_HEADERS = glamor.h -endif +instdir = $(moduledir) INCLUDES = \ $(XORG_INCS) - AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) +libglamor_la_LDFLAGS = -avoid-version + libglamor_la_SOURCES = \ glamor.c \ glamor_copyarea.c \ @@ -45,3 +40,17 @@ libglamor_la_SOURCES = \ glamor_window.c\ glamor_gl_dispatch.c\ glamor.h + +sdk_HEADERS = glamor.h + +if EGL +LIBGLAMOR_EGL = libglamor_egl.la +module_LTLIBRARIES = $(LIBGLAMOR_EGL) +libglamor_egl_la_DEPENDENCIES = libglamor.la +libglamor_egl_la_LDFLAGS = -avoid-version -module $(EGL_LIBS) -lglamor +#libglamor_egl_la_LIBADD = $(top_builddir)/src/libglamor.la +libglamor_egl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c +libglamor_egl_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) +endif + + diff --git a/glamor/glamor.c b/glamor/glamor.c index ee83fd3e9..c96795ced 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -53,57 +53,71 @@ DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index; PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable) { - if (drawable->type == DRAWABLE_WINDOW) - return drawable->pScreen->GetWindowPixmap((WindowPtr)drawable); - else - return (PixmapPtr)drawable; + if (drawable->type == DRAWABLE_WINDOW) + return drawable-> + pScreen->GetWindowPixmap((WindowPtr) drawable); + else + return (PixmapPtr) drawable; } -void +_X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) { - ScreenPtr screen = pixmap->drawable.pScreen; - glamor_pixmap_private *pixmap_priv; + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); - pixmap_priv = glamor_get_pixmap_private(pixmap); - assert(pixmap_priv); - pixmap_priv->tex = tex; + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL) { + pixmap_priv = calloc(sizeof(*pixmap_priv), 1); + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, pixmap_priv); + pixmap_priv->container = pixmap; + pixmap_priv->glamor_priv = glamor_priv; + } - /* Create a framebuffer object wrapping the texture so that we can render - * to it. - */ - pixmap_priv->gl_fbo = 1; - if (tex != 0) { - glamor_pixmap_ensure_fb(pixmap); - pixmap_priv->gl_tex = 1; - } - else { - pixmap_priv->fb = 0; - pixmap_priv->gl_tex = 0; - } - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, - (((w * pixmap->drawable.bitsPerPixel + - 7) / 8) + 3) & ~3, - NULL); + pixmap_priv->tex = tex; + + /* Create a framebuffer object wrapping the texture so that we can render + * to it. + */ + pixmap_priv->gl_fbo = 1; + if (tex != 0) { + glamor_pixmap_ensure_fb(pixmap); + pixmap_priv->gl_tex = 1; + } else { + pixmap_priv->fb = 0; + pixmap_priv->gl_tex = 0; + } + + if (pixmap->devKind == 0) + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + (((w * + pixmap->drawable. + bitsPerPixel + 7) / 8) + + 3) & ~3, 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) +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); + PixmapPtr pixmap = screen->GetScreenPixmap(screen); + glamor_pixmap_private *pixmap_priv; + 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; - pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; + glamor_set_pixmap_texture(pixmap, w, h, tex); + pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_priv->screen_fbo = pixmap_priv->fb; } -#define GLAMOR_PIXMAP_MEMORY 0 -#define GLAMOR_PIXMAP_TEXTURE 1 +#define GLAMOR_PIXMAP_MEMORY 0 +#define GLAMOR_PIXMAP_TEXTURE 1 @@ -111,113 +125,138 @@ static PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { - PixmapPtr pixmap; - GLenum format; - GLuint tex; - int type = GLAMOR_PIXMAP_TEXTURE; - glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (w > 32767 || h > 32767) - return NullPixmap; + PixmapPtr pixmap; + GLenum format; + GLuint tex; + int type = GLAMOR_PIXMAP_TEXTURE; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + if (w > 32767 || h > 32767) + return NullPixmap; - if (!glamor_check_fbo_size(glamor_priv, w,h) - || !glamor_check_fbo_depth(depth) - || usage == GLAMOR_CREATE_PIXMAP_CPU) { - /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. - If we exceed such limitation, we have to use framebuffer.*/ - type = GLAMOR_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); + if (!glamor_check_fbo_size(glamor_priv, w, h) + || !glamor_check_fbo_depth(depth) + || usage == GLAMOR_CREATE_PIXMAP_CPU) { + /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. + If we exceed such limitation, we have to use framebuffer. */ + type = GLAMOR_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); #if 0 - if (usage != GLAMOR_CREATE_PIXMAP_CPU) - glamor_fallback("choose cpu memory for pixmap %p ," - " %d x %d depth %d\n", pixmap, w, h, depth); + if (usage != GLAMOR_CREATE_PIXMAP_CPU) + glamor_fallback("choose cpu memory for pixmap %p ," + " %d x %d depth %d\n", pixmap, w, + h, depth); #endif - } else - pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); + } else + 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 = calloc(1, sizeof(*pixmap_priv)); + dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, + pixmap_priv); + pixmap_priv->container = pixmap; + pixmap_priv->glamor_priv = glamor_priv; - pixmap_priv = glamor_get_pixmap_private(pixmap); - pixmap_priv->container = pixmap; - pixmap_priv->glamor_priv = glamor_priv; + if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) + return pixmap; - if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) + switch (depth) { +#if 0 + case 8: + format = GL_ALPHA; + break; +#endif + case 24: + format = GL_RGB; + break; + default: + format = GL_RGBA; + break; + } + + /* Create the texture used to store the pixmap's data. */ + dispatch->glGenTextures(1, &tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, + GL_UNSIGNED_BYTE, NULL); + + glamor_set_pixmap_texture(pixmap, w, h, tex); return pixmap; +} - switch (depth) { -#if 0 - case 8: - format = GL_ALPHA; - break; -#endif - case 24: - format = GL_RGB; - break; - default: - format = GL_RGBA; - break; - } - - /* Create the texture used to store the pixmap's data. */ - dispatch->glGenTextures(1, &tex); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, - format, GL_UNSIGNED_BYTE, NULL); - - glamor_set_pixmap_texture(pixmap, w, h, tex); - return pixmap; +void +glamor_destroy_textured_pixmap(PixmapPtr pixmap) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + if (pixmap->refcnt == 1) { + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + if (pixmap_priv != NULL) { + if (pixmap_priv->fb) + dispatch->glDeleteFramebuffers(1, + &pixmap_priv->fb); + if (pixmap_priv->tex) + dispatch->glDeleteTextures(1, + &pixmap_priv->tex); + if (pixmap_priv->pbo) + dispatch->glDeleteBuffers(1, + &pixmap_priv->pbo); + free(pixmap_priv); + } + } } static Bool glamor_destroy_pixmap(PixmapPtr pixmap) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (pixmap->refcnt == 1) { - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - dixFreePrivates(pixmap->devPrivates, PRIVATE_PIXMAP); - } + glamor_destroy_textured_pixmap(pixmap); + return fbDestroyPixmap(pixmap); +} - return fbDestroyPixmap(pixmap); +void +glamor_block_handler(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + + dispatch->glFlush(); } static void -glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask) +_glamor_block_handler(void *data, OSTimePtr timeout, + void *last_select_mask) { - glamor_gl_dispatch *dispatch = data; - dispatch->glFlush(); + glamor_gl_dispatch *dispatch = data; + dispatch->glFlush(); } static void -glamor_wakeup_handler(void *data, int result, void *last_select_mask) +_glamor_wakeup_handler(void *data, int result, void *last_select_mask) { } -static void +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; + 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; @@ -226,176 +265,198 @@ int glamor_debug_level; Bool glamor_init(ScreenPtr screen, unsigned int flags) { - glamor_screen_private *glamor_priv; - int gl_version; + glamor_screen_private *glamor_priv; + int gl_version; #ifdef RENDER - PictureScreenPtr ps = GetPictureScreenIfSet(screen); + PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif - if (flags & ~GLAMOR_VALID_FLAGS) { - ErrorF("glamor_init: Invalid flags %x\n", flags); - return FALSE; - } - glamor_priv = calloc(1, sizeof(*glamor_priv)); - if (glamor_priv == NULL) - return FALSE; + if (flags & ~GLAMOR_VALID_FLAGS) { + ErrorF("glamor_init: Invalid flags %x\n", flags); + return FALSE; + } + glamor_priv = calloc(1, sizeof(*glamor_priv)); + if (glamor_priv == NULL) + return FALSE; - if (flags & GLAMOR_INVERTED_Y_AXIS) { - glamor_priv->yInverted = 1; - } else - glamor_priv->yInverted = 0; + if (flags & GLAMOR_INVERTED_Y_AXIS) { + glamor_priv->yInverted = 1; + } else + glamor_priv->yInverted = 0; - if (!dixRegisterPrivateKey(glamor_screen_private_key,PRIVATE_SCREEN, - 0)) { - LogMessage(X_WARNING, - "glamor%d: Failed to allocate screen private\n", - screen->myNum); - goto fail; - } + if (!dixRegisterPrivateKey + (glamor_screen_private_key, PRIVATE_SCREEN, 0)) { + LogMessage(X_WARNING, + "glamor%d: Failed to allocate screen private\n", + screen->myNum); + goto fail; + } - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, + glamor_priv); - if (!dixRegisterPrivateKey(glamor_pixmap_private_key,PRIVATE_PIXMAP, - sizeof(glamor_pixmap_private))) { - LogMessage(X_WARNING, - "glamor%d: Failed to allocate pixmap private\n", - screen->myNum); - goto fail;; - } + if (!dixRegisterPrivateKey + (glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) { + LogMessage(X_WARNING, + "glamor%d: Failed to allocate pixmap private\n", + screen->myNum); + goto fail;; + } - gl_version = glamor_gl_get_version(); + gl_version = glamor_gl_get_version(); #ifndef GLAMOR_GLES2 - if (gl_version < GLAMOR_GL_VERSION_ENCODE(1,3)) { - ErrorF("Require OpenGL version 1.3 or latter.\n"); - goto fail; - } + if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) { + ErrorF("Require OpenGL version 1.3 or latter.\n"); + goto fail; + } #else - if (gl_version < GLAMOR_GL_VERSION_ENCODE(2,0)) { - ErrorF("Require Open GLES2.0 or latter.\n"); - goto fail; - } + if (gl_version < GLAMOR_GL_VERSION_ENCODE(2, 0)) { + ErrorF("Require Open GLES2.0 or latter.\n"); + goto fail; + } #endif - glamor_gl_dispatch_init(screen, &glamor_priv->dispatch, gl_version); + glamor_gl_dispatch_init(screen, &glamor_priv->dispatch, + gl_version); #ifdef GLAMOR_GLES2 - if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) { - ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); - goto fail; - } + if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) { + ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); + goto fail; + } #endif - glamor_priv->has_pack_invert = glamor_gl_has_extension("GL_MESA_pack_invert"); - glamor_priv->has_fbo_blit = glamor_gl_has_extension("GL_EXT_framebuffer_blit"); - glamor_priv->dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); + glamor_priv->has_pack_invert = + glamor_gl_has_extension("GL_MESA_pack_invert"); + glamor_priv->has_fbo_blit = + glamor_gl_has_extension("GL_EXT_framebuffer_blit"); + glamor_priv->dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, + &glamor_priv->max_fbo_size); - if (!RegisterBlockAndWakeupHandlers(glamor_block_handler, - glamor_wakeup_handler, - (void*)&glamor_priv->dispatch)) { - goto fail; - } + if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, + _glamor_wakeup_handler, + (void *) + &glamor_priv->dispatch)) { + goto fail; + } - glamor_set_debug_level(&glamor_debug_level); - glamor_priv->saved_close_screen = screen->CloseScreen; - screen->CloseScreen = glamor_close_screen; + glamor_set_debug_level(&glamor_debug_level); - glamor_priv->saved_create_gc = screen->CreateGC; - screen->CreateGC = glamor_create_gc; + if (flags & GLAMOR_USE_SCREEN) { + glamor_priv->saved_close_screen = screen->CloseScreen; + screen->CloseScreen = glamor_close_screen; - glamor_priv->saved_create_pixmap = screen->CreatePixmap; - screen->CreatePixmap = glamor_create_pixmap; + glamor_priv->saved_create_gc = screen->CreateGC; + screen->CreateGC = glamor_create_gc; - glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; - screen->DestroyPixmap = glamor_destroy_pixmap; + glamor_priv->saved_create_pixmap = screen->CreatePixmap; + screen->CreatePixmap = glamor_create_pixmap; - glamor_priv->saved_get_spans = screen->GetSpans; - screen->GetSpans = glamor_get_spans; + glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; + screen->DestroyPixmap = glamor_destroy_pixmap; - glamor_priv->saved_get_image = screen->GetImage; - screen->GetImage = miGetImage; + glamor_priv->saved_get_spans = screen->GetSpans; + screen->GetSpans = glamor_get_spans; - glamor_priv->saved_change_window_attributes = screen->ChangeWindowAttributes; - screen->ChangeWindowAttributes = glamor_change_window_attributes; + glamor_priv->saved_get_image = screen->GetImage; + screen->GetImage = miGetImage; - glamor_priv->saved_copy_window = screen->CopyWindow; - screen->CopyWindow = glamor_copy_window; + glamor_priv->saved_change_window_attributes = + screen->ChangeWindowAttributes; + screen->ChangeWindowAttributes = + glamor_change_window_attributes; - glamor_priv->saved_bitmap_to_region = screen->BitmapToRegion; - screen->BitmapToRegion = glamor_bitmap_to_region; + glamor_priv->saved_copy_window = screen->CopyWindow; + screen->CopyWindow = glamor_copy_window; + glamor_priv->saved_bitmap_to_region = + screen->BitmapToRegion; + screen->BitmapToRegion = glamor_bitmap_to_region; + } #ifdef RENDER - glamor_priv->saved_composite = ps->Composite; - ps->Composite = glamor_composite; - glamor_priv->saved_trapezoids = ps->Trapezoids; - ps->Trapezoids = glamor_trapezoids; - glamor_priv->saved_glyphs = ps->Glyphs; - ps->Glyphs = glamor_glyphs; - 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; + if (flags & GLAMOR_USE_PICTURE_SCREEN) { + glamor_priv->saved_composite = ps->Composite; + ps->Composite = glamor_composite; - glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph; - ps->UnrealizeGlyph = glamor_glyph_unrealize; + glamor_priv->saved_trapezoids = ps->Trapezoids; + ps->Trapezoids = glamor_trapezoids; + + glamor_priv->saved_glyphs = ps->Glyphs; + ps->Glyphs = glamor_glyphs; + + glamor_priv->saved_triangles = ps->Triangles; + ps->Triangles = glamor_triangles; + + glamor_priv->saved_create_picture = ps->CreatePicture; + ps->CreatePicture = glamor_create_picture; + + glamor_priv->saved_destroy_picture = ps->DestroyPicture; + ps->DestroyPicture = glamor_destroy_picture; + + glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph; + ps->UnrealizeGlyph = glamor_glyph_unrealize; + } + + glamor_init_composite_shaders(screen); #endif - glamor_init_solid_shader(screen); - glamor_init_tile_shader(screen); - glamor_init_putimage_shaders(screen); - glamor_init_finish_access_shaders(screen); - glamor_pixmap_init(screen); + glamor_init_solid_shader(screen); + glamor_init_tile_shader(screen); + glamor_init_putimage_shaders(screen); + glamor_init_finish_access_shaders(screen); + glamor_pixmap_init(screen); #ifdef GLAMOR_GLES2 - glamor_priv->gl_flavor = GLAMOR_GL_ES2; + glamor_priv->gl_flavor = GLAMOR_GL_ES2; #else - glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; + glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; #endif - return TRUE; + return TRUE; -fail: - free(glamor_priv); - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, NULL); - return FALSE; + fail: + free(glamor_priv); + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, + NULL); + return FALSE; } -Bool +Bool glamor_close_screen(int idx, ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); #ifdef RENDER - PictureScreenPtr ps = GetPictureScreenIfSet(screen); + PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif - glamor_glyphs_fini(screen); - screen->CloseScreen = glamor_priv->saved_close_screen; - screen->CreateGC = glamor_priv->saved_create_gc; - screen->CreatePixmap = glamor_priv->saved_create_pixmap; - screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; - screen->GetSpans = glamor_priv->saved_get_spans; - screen->ChangeWindowAttributes = glamor_priv->saved_change_window_attributes; - screen->CopyWindow = glamor_priv->saved_copy_window; - screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; + glamor_glyphs_fini(screen); + screen->CloseScreen = glamor_priv->saved_close_screen; + screen->CreateGC = glamor_priv->saved_create_gc; + screen->CreatePixmap = glamor_priv->saved_create_pixmap; + screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; + screen->GetSpans = glamor_priv->saved_get_spans; + screen->ChangeWindowAttributes = + glamor_priv->saved_change_window_attributes; + screen->CopyWindow = glamor_priv->saved_copy_window; + screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; #ifdef RENDER - if (ps) { - ps->Composite = glamor_priv->saved_composite; - 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; - } + if (ps) { + ps->Composite = glamor_priv->saved_composite; + 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 - if (glamor_priv->vb) - free(glamor_priv->vb); - free(glamor_priv); - return screen->CloseScreen(idx, screen); - + if (glamor_priv->vb) + free(glamor_priv->vb); + free(glamor_priv); + return screen->CloseScreen(idx, screen); + } void glamor_fini(ScreenPtr screen) { -/* Do nothing currently. */ + /* Do nothing currently. */ } diff --git a/glamor/glamor.h b/glamor/glamor.h index e8719fb2f..f9da4ade8 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -39,25 +39,43 @@ #include "fb.h" #include "fbpict.h" -#endif /* GLAMOR_H */ +#endif /* GLAMOR_H */ -#define GLAMOR_INVERTED_Y_AXIS 1 -#define GLAMOR_HOSTX 2 -#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS | GLAMOR_HOSTX) +#define GLAMOR_INVERTED_Y_AXIS 1 +#define GLAMOR_USE_SCREEN 2 +#define GLAMOR_USE_PICTURE_SCREEN 4 + +#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS \ + | GLAMOR_USE_SCREEN \ + | GLAMOR_USE_PICTURE_SCREEN) #define GLAMOR_EGL_EXTERNAL_BUFFER 3 extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); -extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); -extern _X_EXPORT Bool glamor_glyphs_init (ScreenPtr pScreen); -void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex); +extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, + int w, int h, + unsigned int tex); +extern _X_EXPORT Bool glamor_glyphs_init(ScreenPtr pScreen); +void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, + unsigned int tex); + +extern _X_EXPORT void glamor_destroy_textured_pixmap(PixmapPtr pixmap); +extern _X_EXPORT void glamor_block_handler(ScreenPtr screen); #ifdef GLAMOR_FOR_XORG extern _X_EXPORT Bool glamor_egl_init(ScrnInfoPtr scrn, int fd); -extern _X_EXPORT Bool glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride); -extern _X_EXPORT Bool glamor_create_egl_pixmap_image(PixmapPtr pixmap, int handle, int stride); -extern _X_EXPORT Bool glamor_close_egl_screen(ScreenPtr screen); -extern _X_EXPORT void glamor_free_egl_screen(int scrnIndex, int flags); +extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, + int handle, + int stride); +extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, + int handle, + int stride); + +extern _X_EXPORT Bool glamor_egl_close_screen(ScreenPtr screen); +extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); + +extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); +extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); #endif diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index ec57520e8..b49d8163f 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -35,367 +35,406 @@ static Bool glamor_copy_n_to_n_fbo_blit(DrawablePtr src, DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy) + GCPtr gc, BoxPtr box, int nbox, int dx, int dy) { - ScreenPtr screen = dst->pScreen; - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - glamor_pixmap_private *src_pixmap_priv; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - int dst_x_off, dst_y_off, src_x_off, src_y_off, i; + ScreenPtr screen = dst->pScreen; + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + glamor_pixmap_private *src_pixmap_priv; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + int dst_x_off, dst_y_off, src_x_off, src_y_off, i; - if (!glamor_priv->has_fbo_blit) { - glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n"); - return FALSE; - } - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - - if (src_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) - return FALSE; - - if (gc) { - if (gc->alu != GXcopy) { - glamor_delayed_fallback(screen, "non-copy ALU\n"); - return FALSE; + if (!glamor_priv->has_fbo_blit) { + glamor_delayed_fallback(screen, + "no EXT_framebuffer_blit\n"); + return FALSE; } - if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_delayed_fallback(screen, "non-solid planemask\n"); - return FALSE; + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + + if (src_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) + return FALSE; + + if (gc) { + if (gc->alu != GXcopy) { + glamor_delayed_fallback(screen, "non-copy ALU\n"); + return FALSE; + } + if (!glamor_pm_is_solid(dst, gc->planemask)) { + glamor_delayed_fallback(screen, + "non-solid planemask\n"); + 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; - } - glamor_validate_pixmap(dst_pixmap); - - dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fb); - 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); - src_y_off += dy; - - for (i = 0; i < nbox; i++) { - if(glamor_priv->yInverted) { - dispatch->glBlitFramebuffer((box[i].x1 + dx + src_x_off), - (box[i].y1 + src_y_off), - (box[i].x2 + dx + src_x_off), - (box[i].y2 + src_y_off), - (box[i].x1 + dst_x_off), - (box[i].y1 + dst_y_off), - (box[i].x2 + dst_x_off), - (box[i].y2 + dst_y_off), - GL_COLOR_BUFFER_BIT, - GL_NEAREST); - } else { - int flip_dst_y1 = dst_pixmap->drawable.height - (box[i].y2 + dst_y_off); - int flip_dst_y2 = dst_pixmap->drawable.height - (box[i].y1 + dst_y_off); - int flip_src_y1 = src_pixmap->drawable.height - (box[i].y2 + src_y_off); - int flip_src_y2 = src_pixmap->drawable.height - (box[i].y1 + src_y_off); - - dispatch->glBlitFramebuffer(box[i].x1 + dx + src_x_off, - flip_src_y1, - box[i].x2 + dx + src_x_off, - flip_src_y2, - box[i].x1 + dst_x_off, - flip_dst_y1, - box[i].x2 + dst_x_off, - flip_dst_y2, - GL_COLOR_BUFFER_BIT, - GL_NEAREST); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { + glamor_delayed_fallback(screen, "no src fbo\n"); + return FALSE; } - } - return TRUE; + + if (glamor_set_destination_pixmap(dst_pixmap)) { + return FALSE; + } + glamor_validate_pixmap(dst_pixmap); + + dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, + src_pixmap_priv->fb); + 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); + src_y_off += dy; + + for (i = 0; i < nbox; i++) { + if (glamor_priv->yInverted) { + dispatch->glBlitFramebuffer((box[i].x1 + dx + + src_x_off), + (box[i].y1 + + src_y_off), + (box[i].x2 + dx + + src_x_off), + (box[i].y2 + + src_y_off), + (box[i].x1 + + dst_x_off), + (box[i].y1 + + dst_y_off), + (box[i].x2 + + dst_x_off), + (box[i].y2 + + dst_y_off), + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + } else { + int flip_dst_y1 = + dst_pixmap->drawable.height - (box[i].y2 + + dst_y_off); + int flip_dst_y2 = + dst_pixmap->drawable.height - (box[i].y1 + + dst_y_off); + int flip_src_y1 = + src_pixmap->drawable.height - (box[i].y2 + + src_y_off); + int flip_src_y2 = + src_pixmap->drawable.height - (box[i].y1 + + src_y_off); + + dispatch->glBlitFramebuffer(box[i].x1 + dx + + src_x_off, + flip_src_y1, + box[i].x2 + dx + + src_x_off, + flip_src_y2, + box[i].x1 + + dst_x_off, + flip_dst_y1, + box[i].x2 + + dst_x_off, + flip_dst_y2, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + } + } + return TRUE; } #endif static Bool glamor_copy_n_to_n_textured(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy - ) + DrawablePtr dst, + GCPtr gc, BoxPtr box, int nbox, int dx, int dy) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(dst->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - int i; - float vertices[8], texcoords[8]; - glamor_pixmap_private *src_pixmap_priv; - glamor_pixmap_private *dst_pixmap_priv; - int src_x_off, src_y_off, dst_x_off, dst_y_off; - enum glamor_pixmap_status src_status = GLAMOR_NONE; - GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; - int flush_needed = 0; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(dst->pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + int i; + float vertices[8], texcoords[8]; + glamor_pixmap_private *src_pixmap_priv; + glamor_pixmap_private *dst_pixmap_priv; + int src_x_off, src_y_off, dst_x_off, dst_y_off; + enum glamor_pixmap_status src_status = GLAMOR_NONE; + GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; + int flush_needed = 0; - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\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 (!src_pixmap_priv->gl_fbo) { + if (!src_pixmap_priv->gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); - goto fail; + glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); + goto fail; #else - src_status = glamor_upload_pixmap_to_texture(src_pixmap); - if (src_status != GLAMOR_UPLOAD_DONE) - goto fail; + src_status = glamor_upload_pixmap_to_texture(src_pixmap); + if (src_status != GLAMOR_UPLOAD_DONE) + goto fail; #endif - } - else - flush_needed = 1; + } else + flush_needed = 1; - if (gc) { - glamor_set_alu(dispatch, gc->alu); - if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - goto fail; - if (gc->alu != GXcopy) { - glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); - glamor_validate_pixmap(src_pixmap); - } - } + if (gc) { + glamor_set_alu(dispatch, gc->alu); + if (!glamor_set_planemask(dst_pixmap, gc->planemask)) + goto fail; + if (gc->alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc + (src_pixmap_priv); + glamor_validate_pixmap(src_pixmap); + } + } - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - glamor_validate_pixmap(dst_pixmap); + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(dst_pixmap); - pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, + &dst_y_off); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - dx += src_x_off; - dy += src_y_off; - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, + &src_y_off); + dx += src_x_off; + dy += src_y_off; + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, + &src_yscale); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, + src_pixmap_priv->tex); #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0], 1); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); - - } - else { - GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, src_pixmap_priv); - } - - for (i = 0; i < nbox; i++) { + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, - box[i].x1 + dst_x_off, - box[i].y1 + dst_y_off, - box[i].x2 + dst_x_off, - box[i].y2 + dst_y_off, - glamor_priv->yInverted, - vertices); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); + dispatch-> + glUniform1i(glamor_priv->finish_access_no_revert[0], + 1); + dispatch-> + glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) - glamor_set_normalize_tcoords(src_xscale, src_yscale, - box[i].x1 + dx, box[i].y1 + dy, - box[i].x2 + dx, box[i].y2 + dy, - glamor_priv->yInverted, - texcoords); + } else { + GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, + src_pixmap_priv); + } - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } + for (i = 0; i < nbox; i++) { - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, + box[i].x1 + dst_x_off, + box[i].y1 + dst_y_off, + box[i].x2 + dst_x_off, + box[i].y2 + dst_y_off, + glamor_priv->yInverted, + vertices); + + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) + glamor_set_normalize_tcoords(src_xscale, + src_yscale, + box[i].x1 + dx, + box[i].y1 + dy, + box[i].x2 + dx, + box[i].y2 + dy, + glamor_priv->yInverted, + texcoords); + + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - } - dispatch->glUseProgram(0); - /* The source texture is bound to a fbo, we have to flush it here. */ - if (flush_needed) - dispatch->glFlush(); - return TRUE; + } + dispatch->glUseProgram(0); + /* The source texture is bound to a fbo, we have to flush it here. */ + if (flush_needed) + dispatch->glFlush(); + return TRUE; -fail: - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(dst_pixmap, ~0); - return FALSE; + fail: + glamor_set_alu(dispatch, GXcopy); + glamor_set_planemask(dst_pixmap, ~0); + return FALSE; } void glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, - Pixel bitplane, - void *closure) + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure) { - glamor_access_t dst_access; - PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; - DrawablePtr temp_src = src; - glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; - BoxRec bound; - ScreenPtr screen; - int temp_dx = dx; - int temp_dy = dy; - int src_x_off, src_y_off, dst_x_off, dst_y_off; - int i; - int overlaped = 0; - - dst_pixmap = glamor_get_drawable_pixmap(dst); - dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - src_pixmap = glamor_get_drawable_pixmap(src); - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - screen = dst_pixmap->drawable.pScreen; + glamor_access_t dst_access; + PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; + DrawablePtr temp_src = src; + glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; + BoxRec bound; + ScreenPtr screen; + int temp_dx = dx; + int temp_dy = dy; + int src_x_off, src_y_off, dst_x_off, dst_y_off; + int i; + int overlaped = 0; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); - goto fail; - } + dst_pixmap = glamor_get_drawable_pixmap(dst); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + src_pixmap = glamor_get_drawable_pixmap(src); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + screen = dst_pixmap->drawable.pScreen; - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + glamor_fallback("dest pixmap %p has no fbo. \n", + dst_pixmap); + goto fail; + } - if (src_pixmap_priv->fb == dst_pixmap_priv->fb) { - int x_shift = abs(src_x_off - dx - dst_x_off); - int y_shift = abs(src_y_off - dy - dst_y_off); - for ( i = 0; i < nbox; i++) - { - if (x_shift < abs(box[i].x2 - box[i].x1) - && y_shift < abs(box[i].y2 - box[i].y1)) { - overlaped = 1; - break; - } - } - } - /* XXX need revisit to handle overlapped area copying. */ + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, + &src_y_off); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, + &dst_y_off); + + if (src_pixmap_priv->fb == dst_pixmap_priv->fb) { + int x_shift = abs(src_x_off - dx - dst_x_off); + int y_shift = abs(src_y_off - dy - dst_y_off); + for (i = 0; i < nbox; i++) { + if (x_shift < abs(box[i].x2 - box[i].x1) + && y_shift < abs(box[i].y2 - box[i].y1)) { + overlaped = 1; + break; + } + } + } + /* XXX need revisit to handle overlapped area copying. */ #ifndef GLAMOR_GLES2 - if ((overlaped - || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex ) - && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { - goto done; - return; - } -#endif - glamor_calculate_boxes_bound(&bound, box, nbox); - - /* Overlaped indicate the src and dst are the same pixmap. */ - if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) - && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) - * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height))) { - - temp_pixmap = (*screen->CreatePixmap)(screen, - bound.x2 - bound.x1, - bound.y2 - bound.y1, - src_pixmap->drawable.depth, - overlaped ? 0 : GLAMOR_CREATE_PIXMAP_CPU); - if (!temp_pixmap) - goto fail; - glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); - temp_src = &temp_pixmap->drawable; - - if (overlaped) - glamor_copy_n_to_n_textured(src, temp_src, gc, box, nbox, - temp_dx + bound.x1, temp_dy + bound.y1); - else - fbCopyNtoN(src, temp_src, gc, box, nbox, - temp_dx + bound.x1, temp_dy + bound.y1, - reverse, upsidedown, bitplane, - closure); - glamor_transform_boxes(box, nbox, bound.x1, bound.y1); - temp_dx = -bound.x1; - temp_dy = -bound.y1; - } - else { - temp_dx = dx; - temp_dy = dy; - temp_src = src; - } - - if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { - goto done; - } - - - fail: - glamor_report_delayed_fallbacks(src->pScreen); - glamor_report_delayed_fallbacks(dst->pScreen); - - glamor_fallback("from %p to %p (%c,%c)\n", src, dst, - glamor_get_drawable_location(src), - glamor_get_drawable_location(dst)); - - if (gc && gc->alu != GXcopy) - dst_access = GLAMOR_ACCESS_RW; - else - dst_access = GLAMOR_ACCESS_WO; - - if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { - if (dst == src - || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { - fbCopyNtoN(src, dst, gc, box, nbox, - dx, dy, reverse, upsidedown, bitplane, - closure); - if (dst != src) - glamor_finish_access(src); + if ((overlaped + || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex) + && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, + dy)) { + goto done; + return; } - glamor_finish_access(dst); - } +#endif + glamor_calculate_boxes_bound(&bound, box, nbox); -done: - glamor_clear_delayed_fallbacks(src->pScreen); - glamor_clear_delayed_fallbacks(dst->pScreen); - if (temp_src != src) { - (*screen->DestroyPixmap)(temp_pixmap); - } + /* Overlaped indicate the src and dst are the same pixmap. */ + if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) + && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) + * 4 > + src_pixmap->drawable.width * + src_pixmap->drawable.height))) { + + temp_pixmap = (*screen->CreatePixmap) (screen, + bound.x2 - bound.x1, + bound.y2 - bound.y1, + src_pixmap-> + drawable.depth, + overlaped ? 0 : + GLAMOR_CREATE_PIXMAP_CPU); + if (!temp_pixmap) + goto fail; + glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + temp_src = &temp_pixmap->drawable; + + if (overlaped) + glamor_copy_n_to_n_textured(src, temp_src, gc, box, + nbox, + temp_dx + bound.x1, + temp_dy + bound.y1); + else + fbCopyNtoN(src, temp_src, gc, box, nbox, + temp_dx + bound.x1, temp_dy + bound.y1, + reverse, upsidedown, bitplane, closure); + glamor_transform_boxes(box, nbox, bound.x1, bound.y1); + temp_dx = -bound.x1; + temp_dy = -bound.y1; + } else { + temp_dx = dx; + temp_dy = dy; + temp_src = src; + } + + if (glamor_copy_n_to_n_textured + (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { + goto done; + } + + + fail: + glamor_report_delayed_fallbacks(src->pScreen); + glamor_report_delayed_fallbacks(dst->pScreen); + + glamor_fallback("from %p to %p (%c,%c)\n", src, dst, + glamor_get_drawable_location(src), + glamor_get_drawable_location(dst)); + + if (gc && gc->alu != GXcopy) + dst_access = GLAMOR_ACCESS_RW; + else + dst_access = GLAMOR_ACCESS_WO; + + if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { + if (dst == src + || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { + fbCopyNtoN(src, dst, gc, box, nbox, + dx, dy, reverse, upsidedown, bitplane, + closure); + if (dst != src) + glamor_finish_access(src); + } + glamor_finish_access(dst); + } + + done: + glamor_clear_delayed_fallbacks(src->pScreen); + glamor_clear_delayed_fallbacks(dst->pScreen); + if (temp_src != src) { + (*screen->DestroyPixmap) (temp_pixmap); + } } RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, - int srcx, int srcy, int width, int height, int dstx, int dsty) + int srcx, int srcy, int width, int height, int dstx, + int dsty) { - RegionPtr region; - region = miDoCopy(src, dst, gc, - srcx, srcy, width, height, - dstx, dsty, glamor_copy_n_to_n, 0, NULL); + RegionPtr region; + region = miDoCopy(src, dst, gc, + srcx, srcy, width, height, + dstx, dsty, glamor_copy_n_to_n, 0, NULL); - return region; + return region; } diff --git a/glamor/glamor_copywindow.c b/glamor/glamor_copywindow.c index 1e840a934..11b30363f 100644 --- a/glamor/glamor_copywindow.c +++ b/glamor/glamor_copywindow.c @@ -32,29 +32,31 @@ * Screen CopyWindow implementation. */ -void glamor_copy_window(WindowPtr win, DDXPointRec old_origin, - RegionPtr src_region) +void +glamor_copy_window(WindowPtr win, DDXPointRec old_origin, + RegionPtr src_region) { - RegionRec dst_region; - int dx, dy; - PixmapPtr pixmap = win->drawable.pScreen->GetWindowPixmap(win); + RegionRec dst_region; + int dx, dy; + PixmapPtr pixmap = win->drawable.pScreen->GetWindowPixmap(win); - dx = old_origin.x - win->drawable.x; - dy = old_origin.y - win->drawable.y; - REGION_TRANSLATE(win->drawable.pScreen, src_region, -dx, -dy); + dx = old_origin.x - win->drawable.x; + dy = old_origin.y - win->drawable.y; + REGION_TRANSLATE(win->drawable.pScreen, src_region, -dx, -dy); - REGION_INIT(win->drawable.pScreen, &dst_region, NullBox, 0); + REGION_INIT(win->drawable.pScreen, &dst_region, NullBox, 0); - REGION_INTERSECT(win->drawable.pScreen, &dst_region, &win->borderClip, - src_region); + REGION_INTERSECT(win->drawable.pScreen, &dst_region, + &win->borderClip, src_region); #ifdef COMPOSITE - if (pixmap->screen_x || pixmap->screen_y) - REGION_TRANSLATE(win->drawable.pScreen, &dst_region, - -pixmap->screen_x, -pixmap->screen_y); + if (pixmap->screen_x || pixmap->screen_y) + REGION_TRANSLATE(win->drawable.pScreen, &dst_region, + -pixmap->screen_x, -pixmap->screen_y); #endif - miCopyRegion(&pixmap->drawable, &pixmap->drawable, - NULL, &dst_region, dx, dy, glamor_copy_n_to_n, 0, NULL); + miCopyRegion(&pixmap->drawable, &pixmap->drawable, + NULL, &dst_region, dx, dy, glamor_copy_n_to_n, 0, + NULL); - REGION_UNINIT(win->drawable.pScreen, &dst_region); + REGION_UNINIT(win->drawable.pScreen, &dst_region); } diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 2249ac800..8ba938fe3 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -42,215 +42,247 @@ 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); - 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'; + 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'; } GLint -glamor_compile_glsl_prog(glamor_gl_dispatch *dispatch, GLenum type, const char *source) +glamor_compile_glsl_prog(glamor_gl_dispatch * dispatch, GLenum type, + const char *source) { - GLint ok; - GLint prog; + GLint ok; + GLint prog; - prog = dispatch->glCreateShader(type); - dispatch->glShaderSource(prog, 1, (const GLchar **)&source, NULL); - dispatch->glCompileShader(prog); - dispatch->glGetShaderiv(prog, GL_COMPILE_STATUS, &ok); - if (!ok) { - GLchar *info; - GLint size; + prog = dispatch->glCreateShader(type); + dispatch->glShaderSource(prog, 1, (const GLchar **) &source, NULL); + dispatch->glCompileShader(prog); + dispatch->glGetShaderiv(prog, GL_COMPILE_STATUS, &ok); + if (!ok) { + GLchar *info; + GLint size; - dispatch->glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); - info = malloc(size); + dispatch->glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); + info = malloc(size); - dispatch->glGetShaderInfoLog(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"); - } + dispatch->glGetShaderInfoLog(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(glamor_gl_dispatch *dispatch, GLint prog) +glamor_link_glsl_prog(glamor_gl_dispatch * dispatch, GLint prog) { - GLint ok; + GLint ok; - dispatch->glLinkProgram(prog); - dispatch->glGetProgramiv(prog, GL_LINK_STATUS, &ok); - if (!ok) { - GLchar *info; - GLint size; + dispatch->glLinkProgram(prog); + dispatch->glGetProgramiv(prog, GL_LINK_STATUS, &ok); + if (!ok) { + GLchar *info; + GLint size; - dispatch->glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); - info = malloc(size); + dispatch->glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); + info = malloc(size); - dispatch->glGetProgramInfoLog(prog, size, NULL, info); - ErrorF("Failed to link: %s\n", - info); - FatalError("GLSL link failure\n"); - } + dispatch->glGetProgramInfoLog(prog, size, NULL, info); + ErrorF("Failed to link: %s\n", info); + FatalError("GLSL link failure\n"); + } } Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) { - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - return glamor_download_pixmap_to_cpu(pixmap, access); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + 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); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - const char *vs_source = - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord0;\n" - "varying vec2 source_texture;\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - " source_texture = v_texcoord0.xy;\n" - "}\n"; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + const char *vs_source = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "varying vec2 source_texture;\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord0.xy;\n" "}\n"; - const char *fs_source = - GLAMOR_DEFAULT_PRECISION - "varying vec2 source_texture;\n" - "uniform sampler2D sampler;\n" - "uniform int no_revert;\n" - "uniform int swap_rb;\n" - "void main()\n" - "{\n" - " if (no_revert == 1) \n" - " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = texture2D(sampler, source_texture).bgra;\n" - " else \n" - " gl_FragColor = texture2D(sampler, source_texture).rgba;\n" - " } \n" - " else \n" - " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = texture2D(sampler, source_texture).argb;\n" - " else \n" - " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" - " } \n" - "}\n"; - - const char *set_alpha_source = - GLAMOR_DEFAULT_PRECISION - "varying vec2 source_texture;\n" - "uniform sampler2D sampler;\n" - "uniform int no_revert;\n" - "uniform int swap_rb;\n" - "void main()\n" - "{\n" - " if (no_revert == 1) \n" - " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" - " else \n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" - " } \n" - " else \n" - " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" - " else \n" - " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" - " } \n" - "}\n"; - GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; - GLint sampler_uniform_location; + const char *fs_source = + GLAMOR_DEFAULT_PRECISION + "varying vec2 source_texture;\n" + "uniform sampler2D sampler;\n" + "uniform int no_revert;\n" + "uniform int swap_rb;\n" + "void main()\n" + "{\n" + " if (no_revert == 1) \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = texture2D(sampler, source_texture).bgra;\n" + " else \n" + " gl_FragColor = texture2D(sampler, source_texture).rgba;\n" + " } \n" + " else \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = texture2D(sampler, source_texture).argb;\n" + " else \n" + " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" + " } \n" "}\n"; - glamor_priv->finish_access_prog[0] = dispatch->glCreateProgram(); - glamor_priv->finish_access_prog[1] = dispatch->glCreateProgram(); + const char *set_alpha_source = + GLAMOR_DEFAULT_PRECISION + "varying vec2 source_texture;\n" + "uniform sampler2D sampler;\n" + "uniform int no_revert;\n" + "uniform int swap_rb;\n" + "void main()\n" + "{\n" + " if (no_revert == 1) \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" + " else \n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" + " } \n" + " else \n" + " { \n" + " if (swap_rb == 1) \n" + " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" + " else \n" + " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" + " } \n" "}\n"; + GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; + GLint sampler_uniform_location; - vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); - fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, fs_source); - dispatch->glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); - dispatch->glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); + glamor_priv->finish_access_prog[0] = dispatch->glCreateProgram(); + glamor_priv->finish_access_prog[1] = dispatch->glCreateProgram(); - avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); - set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, set_alpha_source); - dispatch->glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); - dispatch->glAttachShader(glamor_priv->finish_access_prog[1], set_alpha_prog); + vs_prog = + glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, + vs_source); + fs_prog = + glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + fs_source); + dispatch->glAttachShader(glamor_priv->finish_access_prog[0], + vs_prog); + dispatch->glAttachShader(glamor_priv->finish_access_prog[0], + fs_prog); - dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_POS, "v_position"); - dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[0]); + avs_prog = + glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, + vs_source); + set_alpha_prog = + glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + set_alpha_source); + dispatch->glAttachShader(glamor_priv->finish_access_prog[1], + avs_prog); + dispatch->glAttachShader(glamor_priv->finish_access_prog[1], + set_alpha_prog); - dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_POS, "v_position"); - dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[1]); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0], + GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0], + GLAMOR_VERTEX_SOURCE, + "v_texcoord0"); + glamor_link_glsl_prog(dispatch, + glamor_priv->finish_access_prog[0]); - glamor_priv->finish_access_no_revert[0] = - dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0], "no_revert"); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1], + GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1], + GLAMOR_VERTEX_SOURCE, + "v_texcoord0"); + glamor_link_glsl_prog(dispatch, + glamor_priv->finish_access_prog[1]); - glamor_priv->finish_access_swap_rb[0] = - dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0], "swap_rb"); - sampler_uniform_location = - dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler"); - dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); - dispatch->glUniform1i(sampler_uniform_location, 0); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0],1); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0],0); - dispatch->glUseProgram(0); + glamor_priv->finish_access_no_revert[0] = + dispatch-> + glGetUniformLocation(glamor_priv->finish_access_prog[0], + "no_revert"); - glamor_priv->finish_access_no_revert[1] = - dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1], "no_revert"); - glamor_priv->finish_access_swap_rb[1] = - dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1], "swap_rb"); - sampler_uniform_location = - dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); - dispatch->glUseProgram(glamor_priv->finish_access_prog[1]); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[1],1); - dispatch->glUniform1i(sampler_uniform_location, 0); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1],0); - dispatch->glUseProgram(0); + glamor_priv->finish_access_swap_rb[0] = + dispatch-> + glGetUniformLocation(glamor_priv->finish_access_prog[0], + "swap_rb"); + sampler_uniform_location = + dispatch-> + glGetUniformLocation(glamor_priv->finish_access_prog[0], + "sampler"); + dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); + dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0], 1); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); + dispatch->glUseProgram(0); + + glamor_priv->finish_access_no_revert[1] = + dispatch-> + glGetUniformLocation(glamor_priv->finish_access_prog[1], + "no_revert"); + glamor_priv->finish_access_swap_rb[1] = + dispatch-> + glGetUniformLocation(glamor_priv->finish_access_prog[1], + "swap_rb"); + sampler_uniform_location = + dispatch-> + glGetUniformLocation(glamor_priv->finish_access_prog[1], + "sampler"); + dispatch->glUseProgram(glamor_priv->finish_access_prog[1]); + dispatch->glUniform1i(glamor_priv->finish_access_no_revert[1], 1); + dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1], 0); + dispatch->glUseProgram(0); } void glamor_finish_access(DrawablePtr drawable) { - 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); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return; + 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); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if ( pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { - glamor_restore_pixmap_to_texture(pixmap); - } + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return; - if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { - assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); - dispatch->glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); - dispatch->glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; - } else { - free(pixmap->devPrivate.ptr); - } + if (pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { + glamor_restore_pixmap_to_texture(pixmap); + } - pixmap->devPrivate.ptr = NULL; + if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { + assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + pixmap_priv->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; + } else { + free(pixmap->devPrivate.ptr); + } + + pixmap->devPrivate.ptr = NULL; } @@ -265,19 +297,21 @@ 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; - } - } - return TRUE; + 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; } /** @@ -286,10 +320,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 @@ -299,31 +333,32 @@ 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; + 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, }; /** @@ -333,91 +368,104 @@ 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 (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. - */ - glamor_fallback("GC %p tile FB_24_32 transformat %p.\n", gc, old_tile); - - 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 ((changes & GCTile) && fbGetRotatedPixmap(gc)) { + gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); + fbGetRotatedPixmap(gc) = 0; + } + + 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. + */ + glamor_fallback + ("GC %p tile FB_24_32 transformat %p.\n", + gc, old_tile); + + 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; + } + } } - if (new_tile) { - fbGetRotatedPixmap(gc) = old_tile; - gc->tile.pixmap = new_tile; - changes |= GCTile; - } - } - } #endif - if (changes & GCTile) { - if (!gc->tileIsPixel) { - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(gc->tile.pixmap); - if ((!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - && FbEvenTile(gc->tile.pixmap->drawable.width * - drawable->bitsPerPixel)) - { - glamor_fallback("GC %p tile changed %p.\n", gc, gc->tile.pixmap); - if (glamor_prepare_access(&gc->tile.pixmap->drawable, - GLAMOR_ACCESS_RW)) { - fbPadPixmap(gc->tile.pixmap); - glamor_finish_access(&gc->tile.pixmap->drawable); - } - } - } - /* Mask out the GCTile change notification, now that we've done FB's - * job for it. - */ - changes &= ~GCTile; - } + if (changes & GCTile) { + if (!gc->tileIsPixel) { + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(gc->tile.pixmap); + if ((!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + && FbEvenTile(gc->tile.pixmap->drawable.width * + drawable->bitsPerPixel)) { + glamor_fallback + ("GC %p tile changed %p.\n", gc, + gc->tile.pixmap); + if (glamor_prepare_access + (&gc->tile.pixmap->drawable, + GLAMOR_ACCESS_RW)) { + fbPadPixmap(gc->tile.pixmap); + glamor_finish_access + (&gc->tile.pixmap->drawable); + } + } + } + /* Mask out the GCTile change notification, now that we've done FB's + * job for it. + */ + 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); - } - } else { - fbValidateGC(gc, changes, drawable); - } + 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; + 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 }; /** @@ -427,69 +475,68 @@ 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; } RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap) { - RegionPtr ret; - glamor_fallback("pixmap %p \n", pixmap); - if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) - return NULL; - ret = fbPixmapToRegion(pixmap); - glamor_finish_access(&pixmap->drawable); - return ret; + RegionPtr ret; + glamor_fallback("pixmap %p \n", pixmap); + if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) + return NULL; + ret = fbPixmapToRegion(pixmap); + glamor_finish_access(&pixmap->drawable); + return ret; } /* Borrow from cairo. */ Bool glamor_gl_has_extension(char *extension) { - const char *gl_extensions; - char *pext; - int ext_len; - ext_len = strlen(extension); - - gl_extensions = (const char*)glGetString(GL_EXTENSIONS); - pext = (char*)gl_extensions; - - if (pext == NULL || extension == NULL) - return FALSE; + const char *gl_extensions; + char *pext; + int ext_len; + ext_len = strlen(extension); - while((pext = strstr(pext, extension)) != NULL) { - if (pext[ext_len] == ' ' || pext[ext_len] == '\0') - return TRUE; - pext += ext_len; - } - return FALSE; + gl_extensions = (const char *) glGetString(GL_EXTENSIONS); + pext = (char *) gl_extensions; + + if (pext == NULL || extension == NULL) + return FALSE; + + while ((pext = strstr(pext, extension)) != NULL) { + if (pext[ext_len] == ' ' || pext[ext_len] == '\0') + return TRUE; + pext += ext_len; + } + return FALSE; } int -glamor_gl_get_version (void) +glamor_gl_get_version(void) { - int major, minor; - const char *version = (const char *) glGetString (GL_VERSION); - const char *dot = version == NULL ? NULL : strchr (version, '.'); - const char *major_start = dot; + int major, minor; + const char *version = (const char *) glGetString(GL_VERSION); + const char *dot = version == NULL ? NULL : strchr(version, '.'); + const char *major_start = dot; - /* Sanity check */ - if (dot == NULL || dot == version || *(dot + 1) == '\0') { - major = 0; - minor = 0; - } else { - /* Find the start of the major version in the string */ - while (major_start > version && *major_start != ' ') - --major_start; - major = strtol (major_start, NULL, 10); - minor = strtol (dot + 1, NULL, 10); - } + /* Sanity check */ + if (dot == NULL || dot == version || *(dot + 1) == '\0') { + major = 0; + minor = 0; + } else { + /* Find the start of the major version in the string */ + while (major_start > version && *major_start != ' ') + --major_start; + major = strtol(major_start, NULL, 10); + minor = strtol(dot + 1, NULL, 10); + } - return GLAMOR_GL_VERSION_ENCODE (major, minor); + return GLAMOR_GL_VERSION_ENCODE(major, minor); } - diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h index 48682e802..b1017490e 100644 --- a/glamor/glamor_debug.h +++ b/glamor/glamor_debug.h @@ -11,7 +11,8 @@ #define GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD 3 extern void -AbortServer(void) _X_NORETURN; +AbortServer(void) + _X_NORETURN; #define GLAMOR_PANIC(_format_, ...) \ do { \ @@ -19,9 +20,9 @@ AbortServer(void) _X_NORETURN; " at %32s line %d: " _format_ "\n", \ __FUNCTION__, __LINE__, \ ##__VA_ARGS__ ); \ - AbortServer(); \ + exit(1); \ } while(0) - + diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 921023eae..9e4804ab4 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -64,10 +64,15 @@ static const char glamor_name[] = "glamor"; +static DevPrivateKeyRec glamor_egl_pixmap_private_key_index; +DevPrivateKey glamor_egl_pixmap_private_key = + &glamor_egl_pixmap_private_key_index; + static void glamor_identify(int flags) { - xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver based.\n", glamor_name); + xf86Msg(X_INFO, "%s: OpenGL accelerated X.org driver based.\n", + glamor_name); } struct glamor_egl_screen_private { @@ -75,51 +80,56 @@ struct glamor_egl_screen_private { EGLContext context; EGLImageKHR root; EGLint major, minor; - + CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; int fd; - int front_buffer_handle; + int front_buffer_handle; int cpp; - struct gbm_device *gbm; + struct gbm_device *gbm; PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; - PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; + PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; - struct glamor_gl_dispatch *dispatch; + struct glamor_gl_dispatch *dispatch; }; int xf86GlamorEGLPrivateIndex = -1; -static struct glamor_egl_screen_private* glamor_get_egl_screen_private(ScrnInfoPtr scrn) +static struct glamor_egl_screen_private +* +glamor_egl_get_screen_private(ScrnInfoPtr scrn) { - return (struct glamor_egl_screen_private *) scrn->privates[xf86GlamorEGLPrivateIndex].ptr; + return (struct glamor_egl_screen_private *) + scrn->privates[xf86GlamorEGLPrivateIndex].ptr; } static EGLImageKHR -_glamor_create_egl_image(struct glamor_egl_screen_private *glamor_egl, int width, int height, int stride, int name) +_glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, + int width, int height, int stride, int name) { EGLImageKHR image; EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA | - EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_STRIDE_MESA, 0, + EGL_DRM_BUFFER_FORMAT_MESA, + EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, + EGL_DRM_BUFFER_USE_SHARE_MESA | + EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; - + attribs[1] = width; attribs[3] = height; - attribs[5] = stride / 4; - image = glamor_egl->egl_create_image_khr (glamor_egl->display, - glamor_egl->context, - EGL_DRM_BUFFER_MESA, - (void*)name, - attribs); + attribs[5] = stride / 4; + image = glamor_egl->egl_create_image_khr(glamor_egl->display, + glamor_egl->context, + EGL_DRM_BUFFER_MESA, + (void *) name, attribs); if (image == EGL_NO_IMAGE_KHR) return EGL_NO_IMAGE_KHR; @@ -130,162 +140,198 @@ _glamor_create_egl_image(struct glamor_egl_screen_private *glamor_egl, int width static int glamor_get_flink_name(int fd, int handle, int *name) { - struct drm_gem_flink flink; - flink.handle = handle; - if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) - return FALSE; - *name = flink.name; - return TRUE; + struct drm_gem_flink flink; + flink.handle = handle; + if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) + return FALSE; + *name = flink.name; + return TRUE; } static Bool -glamor_create_texture_from_image(struct glamor_egl_screen_private *glamor_egl, EGLImageKHR image, GLuint *texture) +glamor_create_texture_from_image(struct glamor_egl_screen_private + *glamor_egl, + EGLImageKHR image, GLuint * texture) { glamor_egl->dispatch->glGenTextures(1, texture); glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, *texture); - glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); - (glamor_egl->egl_image_target_texture2d_oes)(GL_TEXTURE_2D, image); - return TRUE; + (glamor_egl->egl_image_target_texture2d_oes) (GL_TEXTURE_2D, + image); + return TRUE; } Bool -glamor_create_egl_screen_image(ScreenPtr screen, int handle, int stride) +glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); EGLImageKHR image; GLuint texture; - if (!glamor_get_flink_name(glamor_egl->fd, handle, &glamor_egl->front_buffer_handle)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't flink front buffer handle\n"); - return FALSE; - } + if (!glamor_get_flink_name + (glamor_egl->fd, handle, &glamor_egl->front_buffer_handle)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink front buffer handle\n"); + return FALSE; + } - if (glamor_egl->root) { - eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); - glamor_egl->root = EGL_NO_IMAGE_KHR; - } - - image = _glamor_create_egl_image( glamor_egl, - scrn->virtualX, - scrn->virtualY, - stride, - glamor_egl->front_buffer_handle); - if (image == EGL_NO_IMAGE_KHR) - return FALSE; - - glamor_create_texture_from_image(glamor_egl, image, &texture); - glamor_set_screen_pixmap_texture(screen, scrn->virtualX, scrn->virtualY, texture); + if (glamor_egl->root) { + eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); + glamor_egl->root = EGL_NO_IMAGE_KHR; + } + + image = _glamor_egl_create_image(glamor_egl, + scrn->virtualX, + scrn->virtualY, + stride, + glamor_egl->front_buffer_handle); + if (image == EGL_NO_IMAGE_KHR) + return FALSE; + + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_screen_pixmap_texture(screen, scrn->virtualX, + scrn->virtualY, texture); glamor_egl->root = image; - return TRUE; + return TRUE; } /* * This function will be called from the dri buffer allocation. - * It is somehow very familiar with the create screen image. + * It is somehow very familiar with the create textured screen. * XXX the egl image here is not stored at any data structure. * Does this cause a leak problem? */ Bool -glamor_create_egl_pixmap_image(PixmapPtr pixmap, int handle, int stride) +glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); EGLImageKHR image; GLuint texture; - int name; - if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't flink pixmap handle\n"); - return FALSE; - } + int name; + if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink pixmap handle\n"); + return FALSE; + } - image = _glamor_create_egl_image( glamor_egl, - pixmap->drawable.width, - pixmap->drawable.height, - stride, - name); - if (image == EGL_NO_IMAGE_KHR) - return FALSE; - glamor_create_texture_from_image(glamor_egl, image, &texture); - glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, pixmap->drawable.height, texture); - return TRUE; + image = _glamor_egl_create_image(glamor_egl, + pixmap->drawable.width, + pixmap->drawable.height, stride, + name); + if (image == EGL_NO_IMAGE_KHR) { + ErrorF("Failed to create khr image for bo handle %d.\n", handle); + return FALSE; + } + + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, + pixmap->drawable.height, texture); + dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, + image); + return TRUE; +} + +void +glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) +{ + EGLImageKHR image; + ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + + if (pixmap->refcnt == 1) { + image = dixLookupPrivate(&pixmap->devPrivates, + glamor_egl_pixmap_private_key); + if (image != EGL_NO_IMAGE_KHR) + eglDestroyImageKHR(glamor_egl->display, image); + } + glamor_destroy_textured_pixmap(pixmap); } Bool -glamor_close_egl_screen(ScreenPtr screen) +glamor_egl_close_screen(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); glamor_fini(screen); - eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); - + eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); glamor_egl->root = EGL_NO_IMAGE_KHR; return TRUE; } - - static Bool -glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, char *extension) +glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, + char *extension) { - const char *egl_extensions; - char *pext; - int ext_len; - ext_len = strlen(extension); - - egl_extensions = (const char*)eglQueryString(glamor_egl->display, EGL_EXTENSIONS); - pext = (char*)egl_extensions; - - if (pext == NULL || extension == NULL) - return FALSE; - while((pext = strstr(pext, extension)) != NULL) { - if (pext[ext_len] == ' ' || pext[ext_len] == '\0') - return TRUE; - pext += ext_len; - } - return FALSE; + const char *egl_extensions; + char *pext; + int ext_len; + ext_len = strlen(extension); + + egl_extensions = + (const char *) eglQueryString(glamor_egl->display, + EGL_EXTENSIONS); + pext = (char *) egl_extensions; + + if (pext == NULL || extension == NULL) + return FALSE; + while ((pext = strstr(pext, extension)) != NULL) { + if (pext[ext_len] == ' ' || pext[ext_len] == '\0') + return TRUE; + pext += ext_len; + } + return FALSE; } -Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) +Bool +glamor_egl_init(ScrnInfoPtr scrn, int fd) { struct glamor_egl_screen_private *glamor_egl; const char *version; - EGLint config_attribs[] = { + EGLint config_attribs[] = { #ifdef GLAMOR_GLES2 - EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_CONTEXT_CLIENT_VERSION, 2, #endif - EGL_NONE - }; + EGL_NONE + }; - glamor_identify(0); - glamor_egl = calloc(sizeof(*glamor_egl), 1); - if (xf86GlamorEGLPrivateIndex == -1) - xf86GlamorEGLPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + glamor_identify(0); + glamor_egl = calloc(sizeof(*glamor_egl), 1); + if (xf86GlamorEGLPrivateIndex == -1) + xf86GlamorEGLPrivateIndex = + xf86AllocateScrnInfoPrivateIndex(); - scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; + scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; - glamor_egl->fd = fd; + glamor_egl->fd = fd; - glamor_egl->display = eglGetDRMDisplayMESA(glamor_egl->fd); + glamor_egl->display = eglGetDRMDisplayMESA(glamor_egl->fd); - if (glamor_egl->display == EGL_NO_DISPLAY) { - glamor_egl->gbm = gbm_create_device(glamor_egl->fd); - if (glamor_egl->gbm == NULL) { - ErrorF("couldn't get display device\n"); - return FALSE; - } - } + if (glamor_egl->display == EGL_NO_DISPLAY) { + glamor_egl->gbm = gbm_create_device(glamor_egl->fd); + if (glamor_egl->gbm == NULL) { + ErrorF("couldn't get display device\n"); + return FALSE; + } + } glamor_egl->display = eglGetDisplay(glamor_egl->gbm); #ifndef GLAMOR_GLES2 @@ -293,7 +339,9 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) #else eglBindAPI(EGL_OPENGL_ES_API); #endif - if (!eglInitialize(glamor_egl->display, &glamor_egl->major, &glamor_egl->minor)) { + if (!eglInitialize + (glamor_egl->display, &glamor_egl->major, &glamor_egl->minor)) + { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n"); return FALSE; @@ -306,34 +354,36 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT)) { \ ErrorF("EGL_" #EXT "required.\n"); \ return FALSE; \ - } + } - GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); - GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); + GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); + GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); #ifdef GLAMOR_GLES2 - GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_gles2); + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_gles2); #else - GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); + GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); #endif glamor_egl->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA) - eglGetProcAddress("eglExportDRMImageMESA"); - glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) - eglGetProcAddress("eglCreateImageKHR"); + eglGetProcAddress("eglExportDRMImageMESA"); + glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) + eglGetProcAddress("eglCreateImageKHR"); - glamor_egl->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) - eglGetProcAddress("glEGLImageTargetTexture2DOES"); + glamor_egl->egl_image_target_texture2d_oes = + (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) + eglGetProcAddress("glEGLImageTargetTexture2DOES"); - if (!glamor_egl->egl_create_image_khr - || !glamor_egl->egl_export_drm_image_mesa - || !glamor_egl->egl_image_target_texture2d_oes) { + if (!glamor_egl->egl_create_image_khr + || !glamor_egl->egl_export_drm_image_mesa + || !glamor_egl->egl_image_target_texture2d_oes) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetProcAddress() failed\n"); return FALSE; } glamor_egl->context = eglCreateContext(glamor_egl->display, - NULL, EGL_NO_CONTEXT, config_attribs); + NULL, EGL_NO_CONTEXT, + config_attribs); if (glamor_egl->context == EGL_NO_CONTEXT) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create EGL context\n"); @@ -341,44 +391,59 @@ Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) } if (!eglMakeCurrent(glamor_egl->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) { + EGL_NO_SURFACE, EGL_NO_SURFACE, + glamor_egl->context)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to make EGL context current\n"); return FALSE; } - + return TRUE; +} - return TRUE; +Bool +glamor_egl_init_textured_pixmap(ScreenPtr screen) +{ + if (!dixRegisterPrivateKey + (glamor_egl_pixmap_private_key, PRIVATE_PIXMAP, 0)) { + LogMessage(X_WARNING, + "glamor%d: Failed to allocate egl pixmap private\n", + screen->myNum); + return FALSE; + } + return TRUE; } void -glamor_free_egl_screen(int scrnIndex, int flags) +glamor_egl_free_screen(int scrnIndex, int flags) { ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); - if (glamor_egl != NULL) - { - if (!(flags & GLAMOR_EGL_EXTERNAL_BUFFER)) { - eglMakeCurrent(glamor_egl->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (glamor_egl != NULL) { + if (!(flags & GLAMOR_EGL_EXTERNAL_BUFFER)) { + eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); - eglTerminate(glamor_egl->display); - } - free(glamor_egl); + eglTerminate(glamor_egl->display); + } + free(glamor_egl); } } -/* egl version. */ - Bool -glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) +glamor_gl_dispatch_init(ScreenPtr screen, + struct glamor_gl_dispatch *dispatch, + int gl_version) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = glamor_get_egl_screen_private(scrn); - if (!glamor_gl_dispatch_init_impl(dispatch, gl_version, eglGetProcAddress)) - return FALSE; - glamor_egl->dispatch = dispatch; - return TRUE; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + if (!glamor_gl_dispatch_init_impl + (dispatch, gl_version, (get_proc_address_t)eglGetProcAddress)) + return FALSE; + glamor_egl->dispatch = dispatch; + return TRUE; } diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c new file mode 100644 index 000000000..5281ff41d --- /dev/null +++ b/glamor/glamor_eglmodule.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 1998 The XFree86 Project, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + */ + +#include + +#include "xf86Module.h" + +static XF86ModuleVersionInfo VersRec = { + "glamor_egl", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_ANSIC, /* Only need the ansic layer */ + ABI_ANSIC_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} /* signature, to be patched into the file by a tool */ +}; + +_X_EXPORT XF86ModuleData glamor_eglModuleData = { &VersRec, NULL, NULL }; diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 7254167cb..7a4325146 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -32,174 +32,167 @@ * GC fill implementation, based loosely on fb_fill.c */ -void +Bool glamor_fill(DrawablePtr drawable, - GCPtr gc, - int x, - int y, - int width, - int height) + GCPtr gc, int x, int y, int width, int height) { - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); - int off_x, off_y; + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); + int off_x, off_y; - glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y); + glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y); - switch (gc->fillStyle) { - case FillSolid: - if (!glamor_solid(dst_pixmap, - x + off_x, - y + off_y, - width, - height, - gc->alu, - gc->planemask, - gc->fgPixel)) - goto fail; - break; - case FillStippled: - case FillOpaqueStippled: - if (!glamor_stipple(dst_pixmap, - gc->stipple, - x + off_x, - y + off_y, - width, - height, - gc->alu, - gc->planemask, - gc->fgPixel, - gc->bgPixel, - gc->patOrg.x, - gc->patOrg.y)) - goto fail; - return; - break; - case FillTiled: - if (!glamor_tile(dst_pixmap, - gc->tile.pixmap, - x + off_x, - y + off_y, - width, - height, - gc->alu, - gc->planemask, - drawable->x + x + off_x - gc->patOrg.x, - drawable->y + y + off_y - gc->patOrg.y)) - goto fail; - break; - } - return; -fail: - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { - if (glamor_prepare_access_gc(gc)) { - fbFill(drawable, gc, x, y, width, height); - glamor_finish_access_gc(gc); + switch (gc->fillStyle) { + case FillSolid: + if (!glamor_solid(dst_pixmap, + x + off_x, + y + off_y, + width, height, gc->alu, gc->planemask, + gc->fgPixel)) + goto fail; + break; + case FillStippled: + case FillOpaqueStippled: + if (!glamor_stipple(dst_pixmap, + gc->stipple, + x + off_x, + y + off_y, + width, + height, + gc->alu, + gc->planemask, + gc->fgPixel, + gc->bgPixel, gc->patOrg.x, + gc->patOrg.y)) + goto fail; + break; + case FillTiled: + if (!glamor_tile(dst_pixmap, + gc->tile.pixmap, + x + off_x, + y + off_y, + width, + height, + gc->alu, + gc->planemask, + drawable->x + x + off_x - gc->patOrg.x, + drawable->y + y + off_y - gc->patOrg.y)) + goto fail; + break; } - glamor_finish_access(drawable); - } -return; + return TRUE; + fail: + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access_gc(gc)) { + fbFill(drawable, gc, x, y, width, height); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); + } + return TRUE; } void glamor_init_solid_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - const char *solid_vs = - "attribute vec4 v_position;" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - "}\n"; - const char *solid_fs = - GLAMOR_DEFAULT_PRECISION - "uniform vec4 color;\n" - "void main()\n" - "{\n" - " gl_FragColor = color;\n" - "}\n"; - GLint fs_prog, vs_prog; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + const char *solid_vs = + "attribute vec4 v_position;" + "void main()\n" "{\n" " gl_Position = v_position;\n" + "}\n"; + const char *solid_fs = + GLAMOR_DEFAULT_PRECISION "uniform vec4 color;\n" + "void main()\n" "{\n" " gl_FragColor = color;\n" "}\n"; + GLint fs_prog, vs_prog; - glamor_priv->solid_prog = dispatch->glCreateProgram(); - vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs); - fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, solid_fs); - dispatch->glAttachShader(glamor_priv->solid_prog, vs_prog); - dispatch->glAttachShader(glamor_priv->solid_prog, fs_prog); - - dispatch->glBindAttribLocation(glamor_priv->solid_prog, GLAMOR_VERTEX_POS, "v_position"); - glamor_link_glsl_prog(dispatch, glamor_priv->solid_prog); + glamor_priv->solid_prog = dispatch->glCreateProgram(); + vs_prog = + glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs); + fs_prog = + glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + solid_fs); + dispatch->glAttachShader(glamor_priv->solid_prog, vs_prog); + dispatch->glAttachShader(glamor_priv->solid_prog, fs_prog); - glamor_priv->solid_color_uniform_location = - dispatch->glGetUniformLocation(glamor_priv->solid_prog, "color"); + dispatch->glBindAttribLocation(glamor_priv->solid_prog, + GLAMOR_VERTEX_POS, "v_position"); + glamor_link_glsl_prog(dispatch, glamor_priv->solid_prog); + + glamor_priv->solid_color_uniform_location = + dispatch->glGetUniformLocation(glamor_priv->solid_prog, + "color"); } Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, unsigned long fg_pixel) + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel) { - ScreenPtr screen = pixmap->drawable.pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - int x1 = x; - int x2 = x + width; - int y1 = y; - int y2 = y + height; - GLfloat color[4]; - float vertices[8]; - GLfloat xscale, yscale; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("dest %p has no fbo.\n", pixmap); - goto fail; - } - glamor_set_alu(dispatch, alu); - if (!glamor_set_planemask(pixmap, planemask)) { - glamor_fallback("Failedto set planemask in glamor_solid.\n"); - goto fail; - } + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + int x1 = x; + int x2 = x + width; + int y1 = y; + int y2 = y + height; + GLfloat color[4]; + float vertices[8]; + GLfloat xscale, yscale; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("dest %p has no fbo.\n", pixmap); + goto fail; + } + glamor_set_alu(dispatch, alu); + if (!glamor_set_planemask(pixmap, planemask)) { + glamor_fallback + ("Failedto set planemask in glamor_solid.\n"); + goto fail; + } - glamor_get_rgba_from_pixel(fg_pixel, - &color[0], - &color[1], - &color[2], - &color[3], - format_for_pixmap(pixmap)); + glamor_get_rgba_from_pixel(fg_pixel, + &color[0], + &color[1], + &color[2], + &color[3], format_for_pixmap(pixmap)); #ifdef GLAMOR_DELAYED_FILLING - if (x == 0 && y == 0 - && width == pixmap->drawable.width - && height == pixmap->drawable.height - && pixmap_priv->fb != glamor_priv->screen_fbo ) { - pixmap_priv->pending_op.type = GLAMOR_PENDING_FILL; - memcpy(&pixmap_priv->pending_op.fill.color4fv, - color, 4*sizeof(GLfloat)); - pixmap_priv->pending_op.fill.colori = fg_pixel; - return TRUE; - } + if (x == 0 && y == 0 + && width == pixmap->drawable.width + && height == pixmap->drawable.height + && pixmap_priv->fb != glamor_priv->screen_fbo) { + pixmap_priv->pending_op.type = GLAMOR_PENDING_FILL; + memcpy(&pixmap_priv->pending_op.fill.color4fv, + color, 4 * sizeof(GLfloat)); + pixmap_priv->pending_op.fill.colori = fg_pixel; + return TRUE; + } #endif - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); - dispatch->glUseProgram(glamor_priv->solid_prog); - - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color); + dispatch->glUseProgram(glamor_priv->solid_prog); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, color); - glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, - glamor_priv->yInverted, - vertices); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); - return TRUE; -fail: - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(pixmap, ~0); - return FALSE; + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + + glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, + glamor_priv->yInverted, vertices); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + return TRUE; + fail: + glamor_set_alu(dispatch, GXcopy); + glamor_set_planemask(pixmap, ~0); + return FALSE; } - - diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 9a97da250..a91e6a96a 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -32,58 +32,54 @@ void glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, - int n, - DDXPointPtr points, - int *widths, - int sorted) + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) { - DDXPointPtr ppt; - int nbox; - BoxPtr pbox; - int x1, x2, y; - RegionPtr pClip = fbGetCompositeClip(gc); + DDXPointPtr ppt; + int nbox; + BoxPtr pbox; + int x1, x2, y; + RegionPtr pClip = fbGetCompositeClip(gc); - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) - goto fail; + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) + goto fail; ppt = points; - while (n--) { - x1 = ppt->x; - y = ppt->y; - x2 = x1 + (int)*widths; - ppt++; - widths++; + while (n--) { + x1 = ppt->x; + y = ppt->y; + x2 = x1 + (int) *widths; + ppt++; + widths++; - nbox = REGION_NUM_RECTS(pClip); - pbox = REGION_RECTS(pClip); - while (nbox--) { - if (pbox->y1 > y || pbox->y2 <= y) - continue; + nbox = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + while (nbox--) { + if (pbox->y1 > y || pbox->y2 <= y) + continue; - if (x1 < pbox->x1) - x1 = pbox->x1; + if (x1 < pbox->x1) + x1 = pbox->x1; - if (x2 > pbox->x2) - x2 = pbox->x2; + if (x2 > pbox->x2) + x2 = pbox->x2; - if (x2 <= x1) - continue; - glamor_fill (drawable,gc, - x1, y, - x2 - x1 , 1); - pbox++; - } - } - return; -fail: - 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)) { - fbFillSpans(drawable, gc, n, points, widths, sorted); - glamor_finish_access_gc(gc); + if (x2 <= x1) + continue; + glamor_fill(drawable, gc, x1, y, x2 - x1, 1); + pbox++; + } + } + return; + fail: + 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)) { + fbFillSpans(drawable, gc, n, points, widths, + sorted); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); } - glamor_finish_access(drawable); - } } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 224af1ba5..96f51201b 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -34,77 +34,73 @@ void glamor_get_spans(DrawablePtr drawable, int wmax, - DDXPointPtr points, - int *widths, - int count, - char *dst) + DDXPointPtr points, int *widths, int count, char *dst) { - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - GLenum format, type; - int no_alpha, no_revert; - glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - PixmapPtr temp_pixmap = NULL; - int i; - uint8_t *readpixels_dst = (uint8_t *)dst; - int x_off, y_off; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + GLenum format, type; + int no_alpha, no_revert; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(drawable->pScreen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + PixmapPtr temp_pixmap = NULL; + int i; + uint8_t *readpixels_dst = (uint8_t *) dst; + int x_off, y_off; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("pixmap has no fbo.\n"); - goto fail; - } - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &no_revert - )) { - glamor_fallback("unknown depth. %d \n", - drawable->depth); - goto fail; - } - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - /* XXX prepare whole pixmap is not efficient. */ - temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, - &type, no_alpha, no_revert); - pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - } - - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - for (i = 0; i < count; i++) { - if (glamor_priv->yInverted) { - dispatch->glReadPixels(points[i].x + x_off, - (points[i].y + y_off), - widths[i], - 1, - format, type, - readpixels_dst); - } else { - dispatch->glReadPixels(points[i].x + x_off, - pixmap->drawable.height - 1 - (points[i].y + y_off), - widths[i], - 1, - format, type, - readpixels_dst); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("pixmap has no fbo.\n"); + goto fail; } - readpixels_dst += PixmapBytePad(widths[i], drawable->depth); - } - if (temp_pixmap) - pixmap->drawable.pScreen->DestroyPixmap(temp_pixmap); - return; -fail: - 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); - glamor_finish_access(drawable); - } + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + glamor_fallback("unknown depth. %d \n", drawable->depth); + goto fail; + } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + /* XXX prepare whole pixmap is not efficient. */ + temp_pixmap = + glamor_es2_pixmap_read_prepare(pixmap, &format, + &type, no_alpha, + no_revert); + pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + } + + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + for (i = 0; i < count; i++) { + if (glamor_priv->yInverted) { + dispatch->glReadPixels(points[i].x + x_off, + (points[i].y + y_off), + widths[i], 1, format, + type, readpixels_dst); + } else { + dispatch->glReadPixels(points[i].x + x_off, + pixmap->drawable.height - + 1 - (points[i].y + y_off), + widths[i], 1, format, + type, readpixels_dst); + } + readpixels_dst += + PixmapBytePad(widths[i], drawable->depth); + } + if (temp_pixmap) + pixmap->drawable.pScreen->DestroyPixmap(temp_pixmap); + return; + + fail: + 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); + glamor_finish_access(drawable); + } } diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index 823262494..788562c5e 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -3,71 +3,71 @@ #define INIT_FUNC(dst,func_name,get) \ dst->func_name = get(#func_name); \ if (dst->func_name == NULL) \ - { ErrorF("Failed to get fun %s", #func_name); \ + { ErrorF("Failed to get function %s", #func_name); \ goto fail; } -Bool -glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, - int gl_version, - void *(*get_proc_address)(const char*)) +_X_EXPORT Bool +glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, + int gl_version, + void *(*get_proc_address) (const char *)) { - INIT_FUNC(dispatch, glMatrixMode, get_proc_address); - INIT_FUNC(dispatch, glLoadIdentity, get_proc_address); - INIT_FUNC(dispatch, glViewport, get_proc_address); - INIT_FUNC(dispatch, glRasterPos2i, get_proc_address); - INIT_FUNC(dispatch, glDrawArrays, get_proc_address); - INIT_FUNC(dispatch, glReadPixels, get_proc_address); - INIT_FUNC(dispatch, glDrawPixels, get_proc_address); - INIT_FUNC(dispatch, glPixelStorei, get_proc_address); - INIT_FUNC(dispatch, glTexParameteri, get_proc_address); - INIT_FUNC(dispatch, glTexImage2D, get_proc_address); - INIT_FUNC(dispatch, glGenTextures, get_proc_address); - INIT_FUNC(dispatch, glDeleteTextures, get_proc_address); - INIT_FUNC(dispatch, glBindTexture, get_proc_address); - INIT_FUNC(dispatch, glTexSubImage2D, get_proc_address); - INIT_FUNC(dispatch, glFlush, get_proc_address); - INIT_FUNC(dispatch, glGetIntegerv, get_proc_address); - INIT_FUNC(dispatch, glGetString, get_proc_address); - INIT_FUNC(dispatch, glScissor, get_proc_address); - INIT_FUNC(dispatch, glEnable, get_proc_address); - INIT_FUNC(dispatch, glDisable, get_proc_address); - INIT_FUNC(dispatch, glBlendFunc, get_proc_address); - INIT_FUNC(dispatch, glLogicOp, get_proc_address); - INIT_FUNC(dispatch, glActiveTexture, get_proc_address); - INIT_FUNC(dispatch, glGenBuffers, get_proc_address); - INIT_FUNC(dispatch, glBufferData, get_proc_address); - INIT_FUNC(dispatch, glMapBuffer, get_proc_address); - INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); - INIT_FUNC(dispatch, glBindBuffer, get_proc_address); - INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address); - INIT_FUNC(dispatch, glFramebufferTexture2D, get_proc_address); - INIT_FUNC(dispatch, glBindFramebuffer, get_proc_address); - INIT_FUNC(dispatch, glDeleteFramebuffers, get_proc_address); - INIT_FUNC(dispatch, glGenFramebuffers, get_proc_address); - INIT_FUNC(dispatch, glCheckFramebufferStatus, get_proc_address); - INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address); - INIT_FUNC(dispatch, glVertexAttribPointer, get_proc_address); - INIT_FUNC(dispatch, glDisableVertexAttribArray, get_proc_address); - INIT_FUNC(dispatch, glEnableVertexAttribArray, get_proc_address); - INIT_FUNC(dispatch, glBindAttribLocation, get_proc_address); - INIT_FUNC(dispatch, glLinkProgram, get_proc_address); - INIT_FUNC(dispatch, glShaderSource, get_proc_address); + INIT_FUNC(dispatch, glMatrixMode, get_proc_address); + INIT_FUNC(dispatch, glLoadIdentity, get_proc_address); + INIT_FUNC(dispatch, glViewport, get_proc_address); + INIT_FUNC(dispatch, glRasterPos2i, get_proc_address); + INIT_FUNC(dispatch, glDrawArrays, get_proc_address); + INIT_FUNC(dispatch, glReadPixels, get_proc_address); + INIT_FUNC(dispatch, glDrawPixels, get_proc_address); + INIT_FUNC(dispatch, glPixelStorei, get_proc_address); + INIT_FUNC(dispatch, glTexParameteri, get_proc_address); + INIT_FUNC(dispatch, glTexImage2D, get_proc_address); + INIT_FUNC(dispatch, glGenTextures, get_proc_address); + INIT_FUNC(dispatch, glDeleteTextures, get_proc_address); + INIT_FUNC(dispatch, glBindTexture, get_proc_address); + INIT_FUNC(dispatch, glTexSubImage2D, get_proc_address); + INIT_FUNC(dispatch, glFlush, get_proc_address); + INIT_FUNC(dispatch, glGetIntegerv, get_proc_address); + INIT_FUNC(dispatch, glGetString, get_proc_address); + INIT_FUNC(dispatch, glScissor, get_proc_address); + INIT_FUNC(dispatch, glEnable, get_proc_address); + INIT_FUNC(dispatch, glDisable, get_proc_address); + INIT_FUNC(dispatch, glBlendFunc, get_proc_address); + INIT_FUNC(dispatch, glLogicOp, get_proc_address); + INIT_FUNC(dispatch, glActiveTexture, get_proc_address); + INIT_FUNC(dispatch, glGenBuffers, get_proc_address); + INIT_FUNC(dispatch, glBufferData, get_proc_address); + INIT_FUNC(dispatch, glMapBuffer, get_proc_address); + INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); + INIT_FUNC(dispatch, glBindBuffer, get_proc_address); + INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address); + INIT_FUNC(dispatch, glFramebufferTexture2D, get_proc_address); + INIT_FUNC(dispatch, glBindFramebuffer, get_proc_address); + INIT_FUNC(dispatch, glDeleteFramebuffers, get_proc_address); + INIT_FUNC(dispatch, glGenFramebuffers, get_proc_address); + INIT_FUNC(dispatch, glCheckFramebufferStatus, get_proc_address); + INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address); + INIT_FUNC(dispatch, glVertexAttribPointer, get_proc_address); + INIT_FUNC(dispatch, glDisableVertexAttribArray, get_proc_address); + INIT_FUNC(dispatch, glEnableVertexAttribArray, get_proc_address); + INIT_FUNC(dispatch, glBindAttribLocation, get_proc_address); + INIT_FUNC(dispatch, glLinkProgram, get_proc_address); + INIT_FUNC(dispatch, glShaderSource, get_proc_address); - INIT_FUNC(dispatch, glUseProgram, get_proc_address); - INIT_FUNC(dispatch, glUniform1i, get_proc_address); - INIT_FUNC(dispatch, glUniform4f, get_proc_address); - INIT_FUNC(dispatch, glUniform4fv, get_proc_address); - INIT_FUNC(dispatch, glCreateProgram, get_proc_address); - INIT_FUNC(dispatch, glCreateShader, get_proc_address); - INIT_FUNC(dispatch, glCompileShader, get_proc_address); - INIT_FUNC(dispatch, glAttachShader, get_proc_address); - INIT_FUNC(dispatch, glGetShaderiv, get_proc_address); - INIT_FUNC(dispatch, glGetShaderInfoLog, get_proc_address); - INIT_FUNC(dispatch, glGetProgramiv, get_proc_address); - INIT_FUNC(dispatch, glGetProgramInfoLog, get_proc_address); - INIT_FUNC(dispatch, glGetUniformLocation, get_proc_address); + INIT_FUNC(dispatch, glUseProgram, get_proc_address); + INIT_FUNC(dispatch, glUniform1i, get_proc_address); + INIT_FUNC(dispatch, glUniform4f, get_proc_address); + INIT_FUNC(dispatch, glUniform4fv, get_proc_address); + INIT_FUNC(dispatch, glCreateProgram, get_proc_address); + INIT_FUNC(dispatch, glCreateShader, get_proc_address); + INIT_FUNC(dispatch, glCompileShader, get_proc_address); + INIT_FUNC(dispatch, glAttachShader, get_proc_address); + INIT_FUNC(dispatch, glGetShaderiv, get_proc_address); + INIT_FUNC(dispatch, glGetShaderInfoLog, get_proc_address); + INIT_FUNC(dispatch, glGetProgramiv, get_proc_address); + INIT_FUNC(dispatch, glGetProgramInfoLog, get_proc_address); + INIT_FUNC(dispatch, glGetUniformLocation, get_proc_address); - return TRUE; -fail: - return FALSE; + return TRUE; + fail: + return FALSE; } diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index c519667f6..5f1831a7e 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -1,101 +1,123 @@ typedef struct glamor_gl_dispatch { - /* Transformation functions */ - void (*glMatrixMode)(GLenum mode); - void (*glLoadIdentity)(void); - void (*glViewport)( GLint x, GLint y, - GLsizei width, GLsizei height ); - /* Drawing functions */ - void (*glRasterPos2i)( GLint x, GLint y ); + /* Transformation functions */ + void (*glMatrixMode) (GLenum mode); + void (*glLoadIdentity) (void); + void (*glViewport) (GLint x, GLint y, GLsizei width, + GLsizei height); + /* Drawing functions */ + void (*glRasterPos2i) (GLint x, GLint y); - /* Vertex Array */ - void (*glDrawArrays)( GLenum mode, GLint first, GLsizei count ); + /* Vertex Array */ + void (*glDrawArrays) (GLenum mode, GLint first, GLsizei count); - /* Raster functions */ - void (*glReadPixels)( GLint x, GLint y, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - GLvoid *pixels ); + /* Raster functions */ + void (*glReadPixels) (GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid * pixels); - void (*glDrawPixels)( GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels ); - void (*glPixelStorei)( GLenum pname, GLint param ); - /* Texture Mapping */ + void (*glDrawPixels) (GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid * pixels); + void (*glPixelStorei) (GLenum pname, GLint param); + /* Texture Mapping */ - void (*glTexParameteri)( GLenum target, GLenum pname, GLint param ); - void (*glTexImage2D)( GLenum target, GLint level, - GLint internalFormat, - GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, - const GLvoid *pixels ); - /* 1.1 */ - void (*glGenTextures)( GLsizei n, GLuint *textures ); - void (*glDeleteTextures)( GLsizei n, const GLuint *textures); - void (*glBindTexture)( GLenum target, GLuint texture ); - void (*glTexSubImage2D)( GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels ); - /* MISC */ - void (*glFlush)( void ); - void (*glGetIntegerv)( GLenum pname, GLint *params ); - const GLubyte * (*glGetString)( GLenum name ); - void (*glScissor)( GLint x, GLint y, GLsizei width, GLsizei height); - void (*glEnable)( GLenum cap ); - void (*glDisable)( GLenum cap ); - void (*glBlendFunc)( GLenum sfactor, GLenum dfactor ); - void (*glLogicOp)( GLenum opcode ); + void (*glTexParameteri) (GLenum target, GLenum pname, GLint param); + void (*glTexImage2D) (GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, + const GLvoid * pixels); + /* 1.1 */ + void (*glGenTextures) (GLsizei n, GLuint * textures); + void (*glDeleteTextures) (GLsizei n, const GLuint * textures); + void (*glBindTexture) (GLenum target, GLuint texture); + void (*glTexSubImage2D) (GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid * pixels); + /* MISC */ + void (*glFlush) (void); + void (*glGetIntegerv) (GLenum pname, GLint * params); + const GLubyte *(*glGetString) (GLenum name); + void (*glScissor) (GLint x, GLint y, GLsizei width, + GLsizei height); + void (*glEnable) (GLenum cap); + void (*glDisable) (GLenum cap); + void (*glBlendFunc) (GLenum sfactor, GLenum dfactor); + void (*glLogicOp) (GLenum opcode); - /* 1.3 */ - void (*glActiveTexture)( GLenum texture ); + /* 1.3 */ + void (*glActiveTexture) (GLenum texture); - /* GL Extentions */ - void (*glGenBuffers) (GLsizei n, GLuint *buffers); - void (*glBufferData) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); - GLvoid* (*glMapBuffer) (GLenum target, GLenum access); - GLboolean (*glUnmapBuffer) (GLenum target); - void (*glBindBuffer) (GLenum target, GLuint buffer); - void (*glDeleteBuffers) (GLsizei n, const GLuint *buffers); + /* GL Extentions */ + void (*glGenBuffers) (GLsizei n, GLuint * buffers); + void (*glBufferData) (GLenum target, GLsizeiptr size, + const GLvoid * data, GLenum usage); + GLvoid *(*glMapBuffer) (GLenum target, GLenum access); + GLboolean(*glUnmapBuffer) (GLenum target); + void (*glBindBuffer) (GLenum target, GLuint buffer); + void (*glDeleteBuffers) (GLsizei n, const GLuint * buffers); - void (*glFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); - void (*glBindFramebuffer) (GLenum target, GLuint framebuffer); - void (*glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers); - void (*glGenFramebuffers) (GLsizei n, GLuint *framebuffers); - GLenum (*glCheckFramebufferStatus) (GLenum target); - void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + void (*glFramebufferTexture2D) (GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level); + void (*glBindFramebuffer) (GLenum target, GLuint framebuffer); + void (*glDeleteFramebuffers) (GLsizei n, + const GLuint * framebuffers); + void (*glGenFramebuffers) (GLsizei n, GLuint * framebuffers); + GLenum(*glCheckFramebufferStatus) (GLenum target); + void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, + GLint srcY1, GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); - void (*glVertexAttribPointer) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); - void (*glDisableVertexAttribArray) (GLuint index); - void (*glEnableVertexAttribArray) (GLuint index); - void (*glBindAttribLocation) (GLuint program, GLuint index, const GLchar *name); + void (*glVertexAttribPointer) (GLuint index, GLint size, + GLenum type, GLboolean normalized, + GLsizei stride, + const GLvoid * pointer); + void (*glDisableVertexAttribArray) (GLuint index); + void (*glEnableVertexAttribArray) (GLuint index); + void (*glBindAttribLocation) (GLuint program, GLuint index, + const GLchar * name); - void (*glLinkProgram) (GLuint program); - void (*glShaderSource) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); - void (*glUseProgram) (GLuint program); - void (*glUniform1i) (GLint location, GLint v0); - void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); - void (*glUniform4fv) (GLint location, GLsizei count, const GLfloat *value); - GLuint (*glCreateProgram) (void); - GLuint (*glCreateShader) (GLenum type); - void (*glCompileShader) (GLuint shader); - void (*glAttachShader) (GLuint program, GLuint shader); - void (*glGetShaderiv) (GLuint shader, GLenum pname, GLint *params); - void (*glGetShaderInfoLog) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); - void (*glGetProgramiv) (GLuint program, GLenum pname, GLint *params); - void (*glGetProgramInfoLog) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); - GLint (*glGetUniformLocation) (GLuint program, const GLchar *name); + void (*glLinkProgram) (GLuint program); + void (*glShaderSource) (GLuint shader, GLsizei count, + const GLchar * *string, + const GLint * length); + void (*glUseProgram) (GLuint program); + void (*glUniform1i) (GLint location, GLint v0); + void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1, + GLfloat v2, GLfloat v3); + void (*glUniform4fv) (GLint location, GLsizei count, + const GLfloat * value); + GLuint(*glCreateProgram) (void); + GLuint(*glCreateShader) (GLenum type); + void (*glCompileShader) (GLuint shader); + void (*glAttachShader) (GLuint program, GLuint shader); + void (*glGetShaderiv) (GLuint shader, GLenum pname, + GLint * params); + void (*glGetShaderInfoLog) (GLuint shader, GLsizei bufSize, + GLsizei * length, GLchar * infoLog); + void (*glGetProgramiv) (GLuint program, GLenum pname, + GLint * params); + void (*glGetProgramInfoLog) (GLuint program, GLsizei bufSize, + GLsizei * length, GLchar * infoLog); + GLint(*glGetUniformLocation) (GLuint program, + const GLchar * name); -}glamor_gl_dispatch; +} glamor_gl_dispatch; -Bool + +typedef void *(*get_proc_address_t) (const char *); + +_X_EXPORT Bool glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, - int gl_version, - void *(*get_proc_address)(const char*)); - - -Bool -glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version); - + int gl_version, + get_proc_address_t get_proc_address); +_X_EXPORT Bool +glamor_gl_dispatch_init(ScreenPtr screen, + struct glamor_gl_dispatch *dispatch, + int gl_version); diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index af6ec71a1..899dd9d8c 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -66,28 +66,27 @@ */ #define GLYPH_BUFFER_SIZE 1024 -#define CACHE_PICTURE_SIZE 1024 +#define CACHE_PICTURE_SIZE 1024 #define GLYPH_MIN_SIZE 8 #define GLYPH_MAX_SIZE 64 #define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) typedef struct { - PicturePtr source; - glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE]; - int count; + PicturePtr source; + glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE]; + int count; } glamor_glyph_buffer_t; -struct glamor_glyph -{ - glamor_glyph_cache_t *cache; - uint16_t x, y; - uint16_t size, pos; +struct glamor_glyph { + glamor_glyph_cache_t *cache; + uint16_t x, y; + uint16_t size, pos; }; typedef enum { - GLAMOR_GLYPH_SUCCESS, /* Glyph added to render buffer */ - GLAMOR_GLYPH_FAIL, /* out of memory, etc */ - GLAMOR_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ + GLAMOR_GLYPH_SUCCESS, /* Glyph added to render buffer */ + GLAMOR_GLYPH_FAIL, /* out of memory, etc */ + GLAMOR_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ } glamor_glyph_cache_result_t; @@ -96,44 +95,43 @@ typedef enum { static DevPrivateKeyRec glamor_glyph_key; static inline struct glamor_glyph * -glamor_glyph_get_private (GlyphPtr glyph) +glamor_glyph_get_private(GlyphPtr glyph) { - return dixGetPrivate (&glyph->devPrivates, &glamor_glyph_key); + return dixGetPrivate(&glyph->devPrivates, &glamor_glyph_key); } static inline void -glamor_glyph_set_private (GlyphPtr glyph, struct glamor_glyph *priv) +glamor_glyph_set_private(GlyphPtr glyph, struct glamor_glyph *priv) { - dixSetPrivate (&glyph->devPrivates, &glamor_glyph_key, priv); + dixSetPrivate(&glyph->devPrivates, &glamor_glyph_key, priv); } static void -glamor_unrealize_glyph_caches (ScreenPtr pScreen) +glamor_unrealize_glyph_caches(ScreenPtr pScreen) { - glamor_screen_private *glamor = glamor_get_screen_private (pScreen); - int i; + glamor_screen_private *glamor = glamor_get_screen_private(pScreen); + int i; - if (!glamor->glyph_cache_initialized) - return; + if (!glamor->glyph_cache_initialized) + return; - for (i = 0; i < GLAMOR_NUM_GLYPH_CACHE_FORMATS; i++) - { - glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; + for (i = 0; i < GLAMOR_NUM_GLYPH_CACHE_FORMATS; i++) { + glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; - if (cache->picture) - FreePicture (cache->picture, 0); + if (cache->picture) + FreePicture(cache->picture, 0); - if (cache->glyphs) - free (cache->glyphs); - } - glamor->glyph_cache_initialized = FALSE; + if (cache->glyphs) + free(cache->glyphs); + } + glamor->glyph_cache_initialized = FALSE; } void -glamor_glyphs_fini (ScreenPtr pScreen) +glamor_glyphs_fini(ScreenPtr pScreen) { - glamor_unrealize_glyph_caches (pScreen); + glamor_unrealize_glyph_caches(pScreen); } /* All caches for a single format share a single pixmap for glyph storage, @@ -146,220 +144,219 @@ glamor_glyphs_fini (ScreenPtr pScreen) * rest of the allocated structures for all caches with the given format. */ static Bool -glamor_realize_glyph_caches (ScreenPtr pScreen) +glamor_realize_glyph_caches(ScreenPtr pScreen) { - glamor_screen_private *glamor = glamor_get_screen_private (pScreen); - unsigned int formats[] = { - PIXMAN_a8, - PIXMAN_a8r8g8b8, - }; - int i; + glamor_screen_private *glamor = glamor_get_screen_private(pScreen); + unsigned int formats[] = { + PIXMAN_a8, + PIXMAN_a8r8g8b8, + }; + int i; - if (glamor->glyph_cache_initialized) - return TRUE; + if (glamor->glyph_cache_initialized) + return TRUE; - glamor->glyph_cache_initialized = TRUE; - memset (glamor->glyphCaches, 0, sizeof (glamor->glyphCaches)); + glamor->glyph_cache_initialized = TRUE; + memset(glamor->glyphCaches, 0, sizeof(glamor->glyphCaches)); - for (i = 0; i < sizeof (formats) / sizeof (formats[0]); i++) - { - glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; - PixmapPtr pixmap; - PicturePtr picture; - CARD32 component_alpha; - int depth = PIXMAN_FORMAT_DEPTH (formats[i]); - int error; - PictFormatPtr pPictFormat = - PictureMatchFormat (pScreen, depth, formats[i]); - if (!pPictFormat) - goto bail; + for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { + glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; + PixmapPtr pixmap; + PicturePtr picture; + CARD32 component_alpha; + int depth = PIXMAN_FORMAT_DEPTH(formats[i]); + int error; + PictFormatPtr pPictFormat = + PictureMatchFormat(pScreen, depth, formats[i]); + if (!pPictFormat) + goto bail; - /* Now allocate the pixmap and picture */ - pixmap = pScreen->CreatePixmap (pScreen, - CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, - depth, 0); - if (!pixmap) - goto bail; + /* Now allocate the pixmap and picture */ + pixmap = pScreen->CreatePixmap(pScreen, + CACHE_PICTURE_SIZE, + CACHE_PICTURE_SIZE, depth, + 0); + if (!pixmap) + goto bail; - component_alpha = NeedsComponent (pPictFormat->format); - picture = CreatePicture (0, &pixmap->drawable, pPictFormat, - CPComponentAlpha, &component_alpha, - serverClient, &error); + component_alpha = NeedsComponent(pPictFormat->format); + picture = CreatePicture(0, &pixmap->drawable, pPictFormat, + CPComponentAlpha, &component_alpha, + serverClient, &error); - pScreen->DestroyPixmap (pixmap); - if (!picture) - goto bail; + pScreen->DestroyPixmap(pixmap); + if (!picture) + goto bail; - ValidatePicture (picture); + ValidatePicture(picture); - cache->picture = picture; - cache->glyphs = calloc (sizeof (GlyphPtr), GLYPH_CACHE_SIZE); - if (!cache->glyphs) - goto bail; + cache->picture = picture; + cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE); + if (!cache->glyphs) + goto bail; - cache->evict = rand () % GLYPH_CACHE_SIZE; - } - assert (i == GLAMOR_NUM_GLYPH_CACHE_FORMATS); + cache->evict = rand() % GLYPH_CACHE_SIZE; + } + assert(i == GLAMOR_NUM_GLYPH_CACHE_FORMATS); - return TRUE; + return TRUE; -bail: - glamor_unrealize_glyph_caches (pScreen); - return FALSE; + bail: + glamor_unrealize_glyph_caches(pScreen); + return FALSE; } Bool -glamor_glyphs_init (ScreenPtr pScreen) +glamor_glyphs_init(ScreenPtr pScreen) { - if (!dixRegisterPrivateKey (&glamor_glyph_key, PRIVATE_GLYPH, 0)) - return FALSE; + if (!dixRegisterPrivateKey(&glamor_glyph_key, PRIVATE_GLYPH, 0)) + return FALSE; - /* Skip pixmap creation if we don't intend to use it. */ + /* Skip pixmap creation if we don't intend to use it. */ - return glamor_realize_glyph_caches (pScreen); + return glamor_realize_glyph_caches(pScreen); } /* The most efficient thing to way to upload the glyph to the screen * is to use CopyArea; glamor pixmaps are always offscreen. */ static void -glamor_glyph_cache_upload_glyph (ScreenPtr screen, - glamor_glyph_cache_t * cache, - GlyphPtr glyph, int x, int y) +glamor_glyph_cache_upload_glyph(ScreenPtr screen, + glamor_glyph_cache_t * cache, + GlyphPtr glyph, int x, int y) { - PicturePtr pGlyphPicture = GlyphPicture (glyph)[screen->myNum]; - PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; - PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; - PixmapPtr scratch; - GCPtr gc; + PicturePtr pGlyphPicture = GlyphPicture(glyph)[screen->myNum]; + PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; + PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; + PixmapPtr scratch; + GCPtr gc; - gc = GetScratchGC (pCachePixmap->drawable.depth, screen); - if (!gc) - return; + gc = GetScratchGC(pCachePixmap->drawable.depth, screen); + if (!gc) + return; - ValidateGC (&pCachePixmap->drawable, gc); + ValidateGC(&pCachePixmap->drawable, gc); - scratch = pGlyphPixmap; + scratch = pGlyphPixmap; #if 0 - /* Create a temporary bo to stream the updates to the cache */ - if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth || - !uxa_pixmap_is_offscreen (scratch)) - { - scratch = screen->CreatePixmap (screen, - glyph->info.width, - glyph->info.height, - pCachePixmap->drawable.depth, 0); - if (scratch) - { - if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) - { - PicturePtr picture; - int error; + /* Create a temporary bo to stream the updates to the cache */ + if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth || + !uxa_pixmap_is_offscreen(scratch)) { + scratch = screen->CreatePixmap(screen, + glyph->info.width, + glyph->info.height, + pCachePixmap-> + drawable.depth, 0); + if (scratch) { + if (pGlyphPixmap->drawable.depth != + pCachePixmap->drawable.depth) { + PicturePtr picture; + int error; - picture = CreatePicture (0, &scratch->drawable, - PictureMatchFormat (screen, - pCachePixmap-> - drawable.depth, - cache->picture-> - format), 0, NULL, - serverClient, &error); - if (picture) - { - ValidatePicture (picture); - uxa_composite (PictOpSrc, pGlyphPicture, NULL, picture, - 0, 0, - 0, 0, - 0, 0, glyph->info.width, glyph->info.height); - FreePicture (picture, 0); + picture = + CreatePicture(0, + &scratch->drawable, + PictureMatchFormat + (screen, + pCachePixmap-> + drawable.depth, + cache->picture->format), + 0, NULL, serverClient, + &error); + if (picture) { + ValidatePicture(picture); + uxa_composite(PictOpSrc, + pGlyphPicture, + NULL, picture, + 0, 0, 0, 0, 0, + 0, + glyph->info.width, + glyph->info.height); + FreePicture(picture, 0); + } + } else { + glamor_copy_area(&pGlyphPixmap->drawable, + &scratch->drawable, + gc, 0, 0, + glyph->info.width, + glyph->info.height, 0, 0); + } + } else { + scratch = pGlyphPixmap; } - } - else - { - glamor_copy_area (&pGlyphPixmap->drawable, - &scratch->drawable, - gc, - 0, 0, - glyph->info.width, glyph->info.height, 0, 0); - } } - else - { - scratch = pGlyphPixmap; - } - } #endif - glamor_copy_area (&scratch->drawable, &pCachePixmap->drawable, gc, - 0, 0, glyph->info.width, glyph->info.height, x, y); + glamor_copy_area(&scratch->drawable, &pCachePixmap->drawable, gc, + 0, 0, glyph->info.width, glyph->info.height, x, + y); - if (scratch != pGlyphPixmap) - screen->DestroyPixmap (scratch); + if (scratch != pGlyphPixmap) + screen->DestroyPixmap(scratch); - FreeScratchGC (gc); + FreeScratchGC(gc); } void -glamor_glyph_unrealize (ScreenPtr screen, GlyphPtr glyph) +glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph) { - struct glamor_glyph *priv; + struct glamor_glyph *priv; - /* Use Lookup in case we have not attached to this glyph. */ - priv = dixLookupPrivate (&glyph->devPrivates, &glamor_glyph_key); - if (priv == NULL) - return; + /* Use Lookup in case we have not attached to this glyph. */ + priv = dixLookupPrivate(&glyph->devPrivates, &glamor_glyph_key); + if (priv == NULL) + return; - priv->cache->glyphs[priv->pos] = NULL; + priv->cache->glyphs[priv->pos] = NULL; - glamor_glyph_set_private (glyph, NULL); - free (priv); + glamor_glyph_set_private(glyph, NULL); + free(priv); } /* Cut and paste from render/glyph.c - probably should export it instead */ static void -glamor_glyph_extents (int nlist, - GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) +glamor_glyph_extents(int nlist, + GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) { - int x1, x2, y1, y2; - int x, y, n; + int x1, x2, y1, y2; + int x, y, n; - x1 = y1 = MAXSHORT; - x2 = y2 = MINSHORT; - x = y = 0; - while (nlist--) - { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) - { - GlyphPtr glyph = *glyphs++; - int v; + x1 = y1 = MAXSHORT; + x2 = y2 = MINSHORT; + x = y = 0; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + GlyphPtr glyph = *glyphs++; + int v; - v = x - glyph->info.x; - if (v < x1) - x1 = v; - v += glyph->info.width; - if (v > x2) - x2 = v; + v = x - glyph->info.x; + if (v < x1) + x1 = v; + v += glyph->info.width; + if (v > x2) + x2 = v; - v = y - glyph->info.y; - if (v < y1) - y1 = v; - v += glyph->info.height; - if (v > y2) - y2 = v; + v = y - glyph->info.y; + if (v < y1) + y1 = v; + v += glyph->info.height; + if (v > y2) + y2 = v; - x += glyph->info.xOff; - y += glyph->info.yOff; + x += glyph->info.xOff; + y += glyph->info.yOff; + } } - } - extents->x1 = x1 < MINSHORT ? MINSHORT : x1; - extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2; - extents->y1 = y1 < MINSHORT ? MINSHORT : y1; - extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2; + extents->x1 = x1 < MINSHORT ? MINSHORT : x1; + extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2; + extents->y1 = y1 < MINSHORT ? MINSHORT : y1; + extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2; } /** @@ -367,494 +364,488 @@ glamor_glyph_extents (int nlist, * bounding box, which appears to be good enough to catch most cases at least. */ static Bool -glamor_glyphs_intersect (int nlist, GlyphListPtr list, GlyphPtr * glyphs) +glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - int x1, x2, y1, y2; - int n; - int x, y; - BoxRec extents; - Bool first = TRUE; + int x1, x2, y1, y2; + int n; + int x, y; + BoxRec extents; + Bool first = TRUE; - x = 0; - y = 0; - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = 0; - extents.y2 = 0; - while (nlist--) - { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) - { - GlyphPtr glyph = *glyphs++; + x = 0; + y = 0; + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = 0; + extents.y2 = 0; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + GlyphPtr glyph = *glyphs++; - if (glyph->info.width == 0 || glyph->info.height == 0) - { - x += glyph->info.xOff; - y += glyph->info.yOff; - continue; - } + if (glyph->info.width == 0 + || glyph->info.height == 0) { + x += glyph->info.xOff; + y += glyph->info.yOff; + continue; + } - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; - if (first) - { - extents.x1 = x1; - extents.y1 = y1; - extents.x2 = x2; - extents.y2 = y2; - first = FALSE; - } - else - { - if (x1 < extents.x2 && x2 > extents.x1 && - y1 < extents.y2 && y2 > extents.y1) - { - return TRUE; + if (first) { + extents.x1 = x1; + extents.y1 = y1; + extents.x2 = x2; + extents.y2 = y2; + first = FALSE; + } else { + if (x1 < extents.x2 && x2 > extents.x1 + && y1 < extents.y2 + && y2 > extents.y1) { + return TRUE; + } + + if (x1 < extents.x1) + extents.x1 = x1; + if (x2 > extents.x2) + extents.x2 = x2; + if (y1 < extents.y1) + extents.y1 = y1; + if (y2 > extents.y2) + extents.y2 = y2; + } + x += glyph->info.xOff; + y += glyph->info.yOff; } - - if (x1 < extents.x1) - extents.x1 = x1; - if (x2 > extents.x2) - extents.x2 = x2; - if (y1 < extents.y1) - extents.y1 = y1; - if (y2 > extents.y2) - extents.y2 = y2; - } - x += glyph->info.xOff; - y += glyph->info.yOff; } - } - return FALSE; + return FALSE; } static inline unsigned int -glamor_glyph_size_to_count (int size) +glamor_glyph_size_to_count(int size) { - size /= GLYPH_MIN_SIZE; - return size * size; + size /= GLYPH_MIN_SIZE; + return size * size; } static inline unsigned int -glamor_glyph_count_to_mask (int count) +glamor_glyph_count_to_mask(int count) { - return ~(count - 1); + return ~(count - 1); } static inline unsigned int -glamor_glyph_size_to_mask (int size) +glamor_glyph_size_to_mask(int size) { - return glamor_glyph_count_to_mask (glamor_glyph_size_to_count (size)); + return + glamor_glyph_count_to_mask(glamor_glyph_size_to_count(size)); } static PicturePtr -glamor_glyph_cache (ScreenPtr screen, GlyphPtr glyph, int *out_x, int *out_y) +glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, + int *out_y) { - glamor_screen_private *glamor = glamor_get_screen_private (screen); - PicturePtr glyph_picture = GlyphPicture (glyph)[screen->myNum]; - glamor_glyph_cache_t *cache = - &glamor->glyphCaches[PICT_FORMAT_RGB (glyph_picture->format) != 0]; - struct glamor_glyph *priv = NULL; - int size, mask, pos, s; + glamor_screen_private *glamor = glamor_get_screen_private(screen); + PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; + glamor_glyph_cache_t *cache = + &glamor->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != + 0]; + struct glamor_glyph *priv = NULL; + int size, mask, pos, s; - if (glyph->info.width > GLYPH_MAX_SIZE - || glyph->info.height > GLYPH_MAX_SIZE) - return NULL; + if (glyph->info.width > GLYPH_MAX_SIZE + || glyph->info.height > GLYPH_MAX_SIZE) + return NULL; - for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2) - if (glyph->info.width <= size && glyph->info.height <= size) - break; + for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2) + if (glyph->info.width <= size + && glyph->info.height <= size) + break; - s = glamor_glyph_size_to_count (size); - mask = glamor_glyph_count_to_mask (s); - pos = (cache->count + s - 1) & mask; - if (pos < GLYPH_CACHE_SIZE) - { - cache->count = pos + s; - } - else - { - for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) - { - int i = cache->evict & glamor_glyph_size_to_mask (s); - GlyphPtr evicted = cache->glyphs[i]; - if (evicted == NULL) - continue; + s = glamor_glyph_size_to_count(size); + mask = glamor_glyph_count_to_mask(s); + pos = (cache->count + s - 1) & mask; + if (pos < GLYPH_CACHE_SIZE) { + cache->count = pos + s; + } else { + for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) { + int i = + cache->evict & glamor_glyph_size_to_mask(s); + GlyphPtr evicted = cache->glyphs[i]; + if (evicted == NULL) + continue; - priv = glamor_glyph_get_private (evicted); - if (priv->size >= s) - { - cache->glyphs[i] = NULL; - glamor_glyph_set_private (evicted, NULL); - pos = cache->evict & glamor_glyph_size_to_mask (size); - } - else - priv = NULL; - break; - } - if (priv == NULL) - { - int count = glamor_glyph_size_to_count (size); - mask = glamor_glyph_count_to_mask (count); - pos = cache->evict & mask; - for (s = 0; s < count; s++) - { - GlyphPtr evicted = cache->glyphs[pos + s]; - if (evicted != NULL) - { - if (priv != NULL) - free (priv); - - priv = glamor_glyph_get_private (evicted); - glamor_glyph_set_private (evicted, NULL); - cache->glyphs[pos + s] = NULL; + priv = glamor_glyph_get_private(evicted); + if (priv->size >= s) { + cache->glyphs[i] = NULL; + glamor_glyph_set_private(evicted, NULL); + pos = cache->evict & + glamor_glyph_size_to_mask(size); + } else + priv = NULL; + break; } - } + if (priv == NULL) { + int count = glamor_glyph_size_to_count(size); + mask = glamor_glyph_count_to_mask(count); + pos = cache->evict & mask; + for (s = 0; s < count; s++) { + GlyphPtr evicted = cache->glyphs[pos + s]; + if (evicted != NULL) { + if (priv != NULL) + free(priv); + + priv = + glamor_glyph_get_private + (evicted); + glamor_glyph_set_private(evicted, + NULL); + cache->glyphs[pos + s] = NULL; + } + } + } + /* And pick a new eviction position */ + cache->evict = rand() % GLYPH_CACHE_SIZE; } - /* And pick a new eviction position */ - cache->evict = rand () % GLYPH_CACHE_SIZE; - } - if (priv == NULL) - { - priv = malloc (sizeof (struct glamor_glyph)); - if (priv == NULL) - return NULL; - } + if (priv == NULL) { + priv = malloc(sizeof(struct glamor_glyph)); + if (priv == NULL) + return NULL; + } - glamor_glyph_set_private (glyph, priv); - cache->glyphs[pos] = glyph; + glamor_glyph_set_private(glyph, priv); + cache->glyphs[pos] = glyph; - priv->cache = cache; - priv->size = size; - priv->pos = pos; - s = - pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * - (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE)); - priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE; - priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE; - for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) - { - if (pos & 1) - priv->x += s; - if (pos & 2) - priv->y += s; - pos >>= 2; - } + priv->cache = cache; + priv->size = size; + priv->pos = pos; + s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * + (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE)); + priv->x = + s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE; + priv->y = + (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE; + for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) { + if (pos & 1) + priv->x += s; + if (pos & 2) + priv->y += s; + pos >>= 2; + } - glamor_glyph_cache_upload_glyph (screen, cache, glyph, priv->x, priv->y); + glamor_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, + priv->y); - *out_x = priv->x; - *out_y = priv->y; - return cache->picture; + *out_x = priv->x; + *out_y = priv->y; + return cache->picture; } static glamor_glyph_cache_result_t -glamor_buffer_glyph (ScreenPtr screen, - glamor_glyph_buffer_t * buffer, - GlyphPtr glyph, int x_glyph, int y_glyph) +glamor_buffer_glyph(ScreenPtr screen, + glamor_glyph_buffer_t * buffer, + GlyphPtr glyph, int x_glyph, int y_glyph) { - glamor_screen_private *glamor_screen = glamor_get_screen_private (screen); - unsigned int format = (GlyphPicture (glyph)[screen->myNum])->format; - glamor_composite_rect_t *rect; - PicturePtr source; - struct glamor_glyph *priv; - int x, y; - PicturePtr glyph_picture = GlyphPicture (glyph)[screen->myNum]; - glamor_glyph_cache_t *cache; + glamor_screen_private *glamor_screen = + glamor_get_screen_private(screen); + unsigned int format = (GlyphPicture(glyph)[screen->myNum])->format; + glamor_composite_rect_t *rect; + PicturePtr source; + struct glamor_glyph *priv; + int x, y; + PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; + glamor_glyph_cache_t *cache; - if (PICT_FORMAT_BPP (format) == 1) - format = PICT_a8; + if (PICT_FORMAT_BPP(format) == 1) + format = PICT_a8; - cache = &glamor_screen->glyphCaches[PICT_FORMAT_RGB (glyph_picture->format) != 0]; + cache = + &glamor_screen->glyphCaches[PICT_FORMAT_RGB + (glyph_picture->format) != 0]; - if (buffer->source && buffer->source != cache->picture) - return GLAMOR_GLYPH_NEED_FLUSH; + if (buffer->source && buffer->source != cache->picture) + return GLAMOR_GLYPH_NEED_FLUSH; - if (buffer->count == GLYPH_BUFFER_SIZE) - return GLAMOR_GLYPH_NEED_FLUSH; + if (buffer->count == GLYPH_BUFFER_SIZE) + return GLAMOR_GLYPH_NEED_FLUSH; - priv = glamor_glyph_get_private (glyph); + priv = glamor_glyph_get_private(glyph); - if (priv) - { - rect = &buffer->rects[buffer->count++]; - rect->x_src = priv->x; - rect->y_src = priv->y; - if (buffer->source == NULL) buffer->source = priv->cache->picture; - } - else - { - source = glamor_glyph_cache (screen, glyph, &x, &y); - if (source != NULL) - { - rect = &buffer->rects[buffer->count++]; - rect->x_src = x; - rect->y_src = y; - if (buffer->source == NULL) buffer->source = source; + if (priv) { + rect = &buffer->rects[buffer->count++]; + rect->x_src = priv->x; + rect->y_src = priv->y; + if (buffer->source == NULL) + buffer->source = priv->cache->picture; + } else { + source = glamor_glyph_cache(screen, glyph, &x, &y); + if (source != NULL) { + rect = &buffer->rects[buffer->count++]; + rect->x_src = x; + rect->y_src = y; + if (buffer->source == NULL) + buffer->source = source; + } else { + source = GlyphPicture(glyph)[screen->myNum]; + if (buffer->source && buffer->source != source) + return GLAMOR_GLYPH_NEED_FLUSH; + buffer->source = source; + + rect = &buffer->rects[buffer->count++]; + rect->x_src = 0; + rect->y_src = 0; + } } - else - { - source = GlyphPicture (glyph)[screen->myNum]; - if (buffer->source && buffer->source != source) - return GLAMOR_GLYPH_NEED_FLUSH; - buffer->source = source; - rect = &buffer->rects[buffer->count++]; - rect->x_src = 0; - rect->y_src = 0; - } - } + rect->x_dst = x_glyph - glyph->info.x; + rect->y_dst = y_glyph - glyph->info.y; + rect->width = glyph->info.width; + rect->height = glyph->info.height; - rect->x_dst = x_glyph - glyph->info.x; - rect->y_dst = y_glyph - glyph->info.y; - rect->width = glyph->info.width; - rect->height = glyph->info.height; + /* Couldn't find the glyph in the cache, use the glyph picture directly */ - /* Couldn't find the glyph in the cache, use the glyph picture directly */ - - return GLAMOR_GLYPH_SUCCESS; + return GLAMOR_GLYPH_SUCCESS; } static void -glamor_glyphs_flush_mask (PicturePtr mask, glamor_glyph_buffer_t * buffer) +glamor_glyphs_flush_mask(PicturePtr mask, glamor_glyph_buffer_t * buffer) { #ifdef RENDER - glamor_composite_rects (PictOpAdd, buffer->source, NULL, mask, - buffer->count, buffer->rects); + glamor_composite_rects(PictOpAdd, buffer->source, NULL, mask, + buffer->count, buffer->rects); #endif - buffer->count = 0; - buffer->source = NULL; + buffer->count = 0; + buffer->source = NULL; } static void -glamor_glyphs_via_mask (CARD8 op, +glamor_glyphs_via_mask(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, + int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + PixmapPtr mask_pixmap = 0; + PicturePtr mask; + ScreenPtr screen = dst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int x_dst = list->xOff, y_dst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents = { 0, 0, 0, 0 }; + CARD32 component_alpha; + glamor_glyph_buffer_t buffer; + + GCPtr gc; + + glamor_glyph_extents(nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + + if (mask_format->depth == 1) { + PictFormatPtr a8Format = + PictureMatchFormat(screen, 8, PICT_a8); + + if (a8Format) + mask_format = a8Format; + } + + mask_pixmap = screen->CreatePixmap(screen, width, height, + mask_format->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!mask_pixmap) + return; + component_alpha = NeedsComponent(mask_format->format); + mask = CreatePicture(0, &mask_pixmap->drawable, + mask_format, CPComponentAlpha, + &component_alpha, serverClient, &error); + if (!mask) { + screen->DestroyPixmap(mask_pixmap); + return; + } + gc = GetScratchGC(mask_pixmap->drawable.depth, screen); + ValidateGC(&mask_pixmap->drawable, gc); + glamor_fill(&mask_pixmap->drawable, gc, 0, 0, width, height); + FreeScratchGC(gc); + x = -extents.x1; + y = -extents.y1; + + buffer.count = 0; + buffer.source = NULL; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + glyph = *glyphs++; + + if (glyph->info.width > 0 + && glyph->info.height > 0 + && glamor_buffer_glyph(screen, &buffer, + glyph, x, + y) == + GLAMOR_GLYPH_NEED_FLUSH) { + + glamor_glyphs_flush_mask(mask, &buffer); + + glamor_buffer_glyph(screen, &buffer, + glyph, x, y); + } + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + + if (buffer.count) + glamor_glyphs_flush_mask(mask, &buffer); + + x = extents.x1; + y = extents.y1; + CompositePicture(op, + src, + mask, + dst, + x_src + x - x_dst, + y_src + y - y_dst, 0, 0, x, y, width, height); + FreePicture(mask, 0); + screen->DestroyPixmap(mask_pixmap); +} + +static void +glamor_glyphs_flush_dst(CARD8 op, PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, - int nlist, GlyphListPtr list, GlyphPtr * glyphs) + glamor_glyph_buffer_t * buffer, + INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst) { - PixmapPtr mask_pixmap = 0; - PicturePtr mask; - ScreenPtr screen = dst->pDrawable->pScreen; - int width = 0, height = 0; - int x, y; - int x_dst = list->xOff, y_dst = list->yOff; - int n; - GlyphPtr glyph; - int error; - BoxRec extents = { 0, 0, 0, 0 }; - CARD32 component_alpha; - glamor_glyph_buffer_t buffer; - - GCPtr gc; - - glamor_glyph_extents (nlist, list, glyphs, &extents); - - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) - return; - width = extents.x2 - extents.x1; - height = extents.y2 - extents.y1; - - if (mask_format->depth == 1) - { - PictFormatPtr a8Format = PictureMatchFormat (screen, 8, PICT_a8); - - if (a8Format) - mask_format = a8Format; - } - - mask_pixmap = screen->CreatePixmap (screen, width, height, - mask_format->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!mask_pixmap) - return; - component_alpha = NeedsComponent (mask_format->format); - mask = CreatePicture (0, &mask_pixmap->drawable, - mask_format, CPComponentAlpha, - &component_alpha, serverClient, &error); - if (!mask) - { - screen->DestroyPixmap (mask_pixmap); - return; - } - gc = GetScratchGC (mask_pixmap->drawable.depth, screen); - ValidateGC (&mask_pixmap->drawable, gc); - glamor_fill (&mask_pixmap->drawable, gc, 0, 0, width, height); - FreeScratchGC (gc); - x = -extents.x1; - y = -extents.y1; - - buffer.count = 0; - buffer.source = NULL; - while (nlist--) - { - x += list->xOff; - y += list->yOff; - n = list->len; - while (n--) - { - glyph = *glyphs++; - - if (glyph->info.width > 0 && glyph->info.height > 0 && - glamor_buffer_glyph (screen, &buffer, glyph, x, - y) == GLAMOR_GLYPH_NEED_FLUSH) - { - - glamor_glyphs_flush_mask (mask, &buffer); - - glamor_buffer_glyph (screen, &buffer, glyph, x, y); - } - - x += glyph->info.xOff; - y += glyph->info.yOff; + int i; + glamor_composite_rect_t *rect = &buffer->rects[0]; + for (i = 0; i < buffer->count; i++, rect++) { + rect->x_mask = rect->x_src; + rect->y_mask = rect->y_src; + rect->x_src = x_src + rect->x_dst - x_dst; + rect->y_src = y_src + rect->y_dst - y_dst; } - list++; - } - if (buffer.count) - glamor_glyphs_flush_mask (mask, &buffer); + glamor_composite_rects(op, src, buffer->source, dst, + buffer->count, &buffer->rects[0]); - x = extents.x1; - y = extents.y1; - CompositePicture (op, - src, - mask, - dst, - x_src + x - x_dst, - y_src + y - y_dst, 0, 0, x, y, width, height); - FreePicture (mask, 0); - screen->DestroyPixmap (mask_pixmap); + buffer->count = 0; + buffer->source = NULL; } static void -glamor_glyphs_flush_dst (CARD8 op, - PicturePtr src, - PicturePtr dst, - glamor_glyph_buffer_t * buffer, - INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst) +glamor_glyphs_to_dst(CARD8 op, + PicturePtr src, + PicturePtr dst, + INT16 x_src, + INT16 y_src, + int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - int i; - glamor_composite_rect_t *rect = &buffer->rects[0]; - for (i = 0; i < buffer->count; i++, rect++) - { - rect->x_mask = rect->x_src; - rect->y_mask = rect->y_src; - rect->x_src = x_src + rect->x_dst - x_dst; - rect->y_src = y_src + rect->y_dst - y_dst; - } + ScreenPtr screen = dst->pDrawable->pScreen; + int x = 0, y = 0; + int x_dst = list->xOff, y_dst = list->yOff; + int n; + GlyphPtr glyph; + glamor_glyph_buffer_t buffer; - glamor_composite_rects (op, src, buffer->source, dst, - buffer->count, &buffer->rects[0]); + buffer.count = 0; + buffer.source = NULL; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + glyph = *glyphs++; - buffer->count = 0; - buffer->source = NULL; -} + if (glyph->info.width > 0 + && glyph->info.height > 0 + && glamor_buffer_glyph(screen, &buffer, + glyph, x, + y) == + GLAMOR_GLYPH_NEED_FLUSH) { + glamor_glyphs_flush_dst(op, src, dst, + &buffer, x_src, + y_src, x_dst, + y_dst); + glamor_buffer_glyph(screen, &buffer, + glyph, x, y); + } -static void -glamor_glyphs_to_dst (CARD8 op, - PicturePtr src, - PicturePtr dst, - INT16 x_src, - INT16 y_src, - int nlist, GlyphListPtr list, GlyphPtr * glyphs) -{ - ScreenPtr screen = dst->pDrawable->pScreen; - int x = 0, y = 0; - int x_dst = list->xOff, y_dst = list->yOff; - int n; - GlyphPtr glyph; - glamor_glyph_buffer_t buffer; - - buffer.count = 0; - buffer.source = NULL; - while (nlist--) - { - x += list->xOff; - y += list->yOff; - n = list->len; - while (n--) - { - glyph = *glyphs++; - - if (glyph->info.width > 0 && glyph->info.height > 0 && - glamor_buffer_glyph (screen, &buffer, glyph, x, - y) == GLAMOR_GLYPH_NEED_FLUSH) - { - glamor_glyphs_flush_dst (op, src, dst, - &buffer, x_src, y_src, x_dst, y_dst); - glamor_buffer_glyph (screen, &buffer, glyph, x, y); - } - - x += glyph->info.xOff; - y += glyph->info.yOff; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; } - list++; - } - if (buffer.count) - glamor_glyphs_flush_dst (op, src, dst, &buffer, - x_src, y_src, x_dst, y_dst); + if (buffer.count) + glamor_glyphs_flush_dst(op, src, dst, &buffer, + x_src, y_src, x_dst, y_dst); } void -glamor_glyphs (CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +glamor_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ - if (!mask_format) - { - Bool same_format = TRUE; - int i; + /* If we don't have a mask format but all the glyphs have the same format + * and don't intersect, use the glyph format as mask format for the full + * benefits of the glyph cache. + */ + if (!mask_format) { + Bool same_format = TRUE; + int i; - mask_format = list[0].format; + mask_format = list[0].format; - for (i = 0; i < nlist; i++) - { - if (mask_format->format != list[i].format->format) - { - same_format = FALSE; - break; - } + for (i = 0; i < nlist; i++) { + if (mask_format->format != list[i].format->format) { + same_format = FALSE; + break; + } + } + + if (!same_format || (mask_format->depth != 1 && + glamor_glyphs_intersect(nlist, list, + glyphs))) { + mask_format = NULL; + } } - if (!same_format || (mask_format->depth != 1 && - glamor_glyphs_intersect (nlist, list, glyphs))) - { - mask_format = NULL; - } - } - - if (mask_format) - glamor_glyphs_via_mask (op, src, dst, mask_format, - x_src, y_src, nlist, list, glyphs); - else - glamor_glyphs_to_dst (op, src, dst, x_src, y_src, nlist, list, glyphs); + if (mask_format) + glamor_glyphs_via_mask(op, src, dst, mask_format, + x_src, y_src, nlist, list, glyphs); + else + glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, + list, glyphs); } diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index c94c07cd7..9e8d6ec80 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -9,36 +9,36 @@ /* 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 +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); + 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); + 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); + 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); + if (!picture || !picture->pDrawable) + return; + + glamor_finish_access(picture->pDrawable); } /* @@ -49,45 +49,48 @@ glamor_finish_access_picture(PicturePtr picture) int glamor_create_picture(PicturePtr picture) { - PixmapPtr pixmap; - glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv; + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; - if (!picture || !picture->pDrawable) - return 0; + 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); + 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); + 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; + PixmapPtr pixmap; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; - if (!picture || !picture->pDrawable) - return; + 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); + 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); + 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) +void +glamor_picture_format_fixup(PicturePtr picture, + glamor_pixmap_private * pixmap_priv) { - pixmap_priv->pict_format = picture->format; + pixmap_priv->pict_format = picture->format; } - diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 28ad57a4d..f02acc746 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -15,118 +15,123 @@ 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; - } + if (drawable->type == DRAWABLE_WINDOW) { + *x = -pixmap->screen_x; + *y = -pixmap->screen_y; + return; + } #endif - *x = 0; - *y = 0; + *x = 0; + *y = 0; } -static void -_glamor_pixmap_validate_filling(glamor_screen_private *glamor_priv, - glamor_pixmap_private *pixmap_priv) +static void +_glamor_pixmap_validate_filling(glamor_screen_private * glamor_priv, + glamor_pixmap_private * pixmap_priv) { - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - GLfloat vertices[8]; - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(glamor_priv->solid_prog); - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, - 1, pixmap_priv->pending_op.fill.color4fv); - vertices[0] = -1; - vertices[1] = -1; - vertices[2] = 1; - vertices[3] = -1; - vertices[4] = 1; - vertices[5] = 1; - vertices[6] = -1; - vertices[7] = 1; - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); - pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + GLfloat vertices[8]; + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(glamor_priv->solid_prog); + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, pixmap_priv->pending_op.fill.color4fv); + vertices[0] = -1; + vertices[1] = -1; + vertices[2] = 1; + vertices[3] = -1; + vertices[4] = 1; + vertices[5] = 1; + vertices[6] = -1; + vertices[7] = 1; + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; } glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { - NULL, - _glamor_pixmap_validate_filling + NULL, + _glamor_pixmap_validate_filling }; void glamor_pixmap_init(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; } void glamor_validate_pixmap(PixmapPtr pixmap) { - glamor_pixmap_validate_function_t validate_op; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); + glamor_pixmap_validate_function_t validate_op; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); - validate_op = glamor_priv->pixmap_validate_funcs[pixmap_priv->pending_op.type]; - if (validate_op) { - (*validate_op)(glamor_priv, pixmap_priv); - } + validate_op = + glamor_priv->pixmap_validate_funcs[pixmap_priv-> + pending_op.type]; + if (validate_op) { + (*validate_op) (glamor_priv, pixmap_priv); + } } void -glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv) +glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); #ifndef GLAMOR_GLES2 - dispatch->glMatrixMode(GL_PROJECTION); - dispatch->glLoadIdentity(); - dispatch->glMatrixMode(GL_MODELVIEW); - dispatch->glLoadIdentity(); + dispatch->glMatrixMode(GL_PROJECTION); + dispatch->glLoadIdentity(); + dispatch->glMatrixMode(GL_MODELVIEW); + dispatch->glLoadIdentity(); #endif - dispatch->glViewport(0, 0, - pixmap_priv->container->drawable.width, - pixmap_priv->container->drawable.height); + dispatch->glViewport(0, 0, + pixmap_priv->container->drawable.width, + pixmap_priv->container->drawable.height); } int -glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv) +glamor_set_destination_pixmap_priv(glamor_pixmap_private * pixmap_priv) { - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return -1; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return -1; - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - return 0; + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + return 0; } int glamor_set_destination_pixmap(PixmapPtr pixmap) { - int err; - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + int err; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); - err = glamor_set_destination_pixmap_priv(pixmap_priv); - return err; + err = glamor_set_destination_pixmap_priv(pixmap_priv); + return err; } Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) { - if (glamor_pm_is_solid(&pixmap->drawable, planemask)) { - return GL_TRUE; - } + if (glamor_pm_is_solid(&pixmap->drawable, planemask)) { + return GL_TRUE; + } - glamor_fallback("unsupported planemask %lx\n", planemask); - return GL_FALSE; + glamor_fallback("unsupported planemask %lx\n", planemask); + return GL_FALSE; } @@ -135,63 +140,63 @@ void glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) { #ifndef GLAMOR_GLES2 - if (alu == GXcopy) { - dispatch->glDisable(GL_COLOR_LOGIC_OP); - return; - } - dispatch->glEnable(GL_COLOR_LOGIC_OP); - switch (alu) { - case GXclear: - dispatch->glLogicOp(GL_CLEAR); - break; - case GXand: - dispatch->glLogicOp(GL_AND); - break; - case GXandReverse: - dispatch->glLogicOp(GL_AND_REVERSE); - break; - case GXandInverted: - dispatch->glLogicOp(GL_AND_INVERTED); - break; - case GXnoop: - dispatch->glLogicOp(GL_NOOP); - break; - case GXxor: - dispatch->glLogicOp(GL_XOR); - break; - case GXor: - dispatch->glLogicOp(GL_OR); - break; - case GXnor: - dispatch->glLogicOp(GL_NOR); - break; - case GXequiv: - dispatch->glLogicOp(GL_EQUIV); - break; - case GXinvert: - dispatch->glLogicOp(GL_INVERT); - break; - case GXorReverse: - dispatch->glLogicOp(GL_OR_REVERSE); - break; - case GXcopyInverted: - dispatch->glLogicOp(GL_COPY_INVERTED); - break; - case GXorInverted: - dispatch->glLogicOp(GL_OR_INVERTED); - break; - case GXnand: - dispatch->glLogicOp(GL_NAND); - break; - case GXset: - dispatch->glLogicOp(GL_SET); - break; - default: - FatalError("unknown logic op\n"); - } + if (alu == GXcopy) { + dispatch->glDisable(GL_COLOR_LOGIC_OP); + return; + } + dispatch->glEnable(GL_COLOR_LOGIC_OP); + switch (alu) { + case GXclear: + dispatch->glLogicOp(GL_CLEAR); + break; + case GXand: + dispatch->glLogicOp(GL_AND); + break; + case GXandReverse: + dispatch->glLogicOp(GL_AND_REVERSE); + break; + case GXandInverted: + dispatch->glLogicOp(GL_AND_INVERTED); + break; + case GXnoop: + dispatch->glLogicOp(GL_NOOP); + break; + case GXxor: + dispatch->glLogicOp(GL_XOR); + break; + case GXor: + dispatch->glLogicOp(GL_OR); + break; + case GXnor: + dispatch->glLogicOp(GL_NOR); + break; + case GXequiv: + dispatch->glLogicOp(GL_EQUIV); + break; + case GXinvert: + dispatch->glLogicOp(GL_INVERT); + break; + case GXorReverse: + dispatch->glLogicOp(GL_OR_REVERSE); + break; + case GXcopyInverted: + dispatch->glLogicOp(GL_COPY_INVERTED); + break; + case GXorInverted: + dispatch->glLogicOp(GL_OR_INVERTED); + break; + case GXnand: + dispatch->glLogicOp(GL_NAND); + break; + case GXset: + dispatch->glLogicOp(GL_SET); + break; + default: + FatalError("unknown logic op\n"); + } #else - if (alu != GXcopy) - ErrorF("unsupported alu %x \n", alu); + if (alu != GXcopy) + ErrorF("unsupported alu %x \n", alu); #endif } @@ -203,60 +208,62 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) * This texture may not be the one attached to it. **/ int in_restore = 0; -static void -__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, GLuint tex) +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); - glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - unsigned int stride, row_length; - void *texels; - GLenum iformat; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + unsigned int stride, row_length; + void *texels; + GLenum iformat; - switch (pixmap->drawable.depth) { + switch (pixmap->drawable.depth) { #if 0 - case 8: - iformat = GL_ALPHA; - break; + case 8: + iformat = GL_ALPHA; + break; #endif - case 24: - iformat = GL_RGB; - break; - default: - iformat = GL_RGBA; - break; - } + case 24: + iformat = GL_RGB; + break; + default: + iformat = GL_RGBA; + break; + } - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - iformat = format; - } + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + iformat = format; + } - stride = pixmap->devKind; - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + stride = pixmap->devKind; + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - } - else { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + } else { + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } - if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { - texels = NULL; - dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->pbo); - } - else - texels = pixmap->devPrivate.ptr; + if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { + texels = NULL; + dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, + pixmap_priv->pbo); + } else + texels = pixmap->devPrivate.ptr; - dispatch->glTexImage2D(GL_TEXTURE_2D, - 0, - iformat, - pixmap->drawable.width, - pixmap->drawable.height, 0, - format, type, texels); + dispatch->glTexImage2D(GL_TEXTURE_2D, + 0, + iformat, + pixmap->drawable.width, + pixmap->drawable.height, 0, format, type, + texels); } @@ -266,118 +273,142 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, * */ static void -_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, int no_alpha, int no_revert, - int flip) +_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, + GLenum type, int no_alpha, int no_revert, + int flip) { - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - 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; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + 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); + 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 (no_alpha == 0 && no_revert == 1 && !need_flip) { - __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->tex); - return; - } + /* Try fast path firstly, upload the pixmap to the texture attached + * to the fbo directly. */ + if (no_alpha == 0 && no_revert == 1 && !need_flip) { + __glamor_upload_pixmap_to_texture(pixmap, format, type, + pixmap_priv->tex); + return; + } - if (need_flip) - ptexcoords = texcoords; - else - ptexcoords = texcoords_inv; + if (need_flip) + ptexcoords = texcoords; + else + ptexcoords = texcoords_inv; - /* Slow path, we need to flip y or wire alpha to 1. */ - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - ptexcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + /* Slow path, we need to flip y or wire alpha to 1. */ + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + ptexcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - dispatch->glGenTextures(1, &tex); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + dispatch->glGenTextures(1, &tex); - __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); + __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],0); + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv-> + finish_access_no_revert[no_alpha], + no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], + 0); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); #ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glDeleteTextures(1, &tex); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); + dispatch->glUseProgram(0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDeleteTextures(1, &tex); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); } void glamor_pixmap_ensure_fb(PixmapPtr pixmap) { - int status; - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + int status; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - if (pixmap_priv->fb == 0) - dispatch->glGenFramebuffers(1, &pixmap_priv->fb); - assert(pixmap_priv->tex != 0); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - pixmap_priv->tex, - 0); - status = dispatch->glCheckFramebufferStatus (GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - const char *str; - switch (status) { - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break; - case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break; - default: str = "unknown error"; break; - } + if (pixmap_priv->fb == 0) + dispatch->glGenFramebuffers(1, &pixmap_priv->fb); + assert(pixmap_priv->tex != 0); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, pixmap_priv->tex, + 0); + status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + const char *str; + switch (status) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + str = "incomplete attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + str = "incomplete/missing attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + str = "incomplete draw buffer"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + str = "incomplete read buffer"; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + str = "unsupported"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + str = "incomplete multiple"; + break; + default: + str = "unknown error"; + break; + } - LogMessageVerb(X_INFO, 0, - "destination is framebuffer incomplete: %s [%#x]\n", - str, status); - assert(0); - } + LogMessageVerb(X_INFO, 0, + "destination is framebuffer incomplete: %s [%#x]\n", + str, status); + assert(0); + } } /* @@ -390,102 +421,115 @@ glamor_pixmap_ensure_fb(PixmapPtr pixmap) static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) { - int need_fbo; - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + int need_fbo; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (!glamor_check_fbo_size(glamor_priv, 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_check_fbo_size + (glamor_priv, 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 (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return 0; - if (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) - need_fbo = 1; - else - need_fbo = 0; + if (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) + need_fbo = 1; + else + need_fbo = 0; - if (pixmap_priv->tex == 0) - dispatch->glGenTextures(1, &pixmap_priv->tex); + if (pixmap_priv->tex == 0) + dispatch->glGenTextures(1, &pixmap_priv->tex); - if (need_fbo) { - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixmap->drawable.width, - pixmap->drawable.height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glamor_pixmap_ensure_fb(pixmap); - } - - return 0; + if (need_fbo) { + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + pixmap->drawable.width, + pixmap->drawable.height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + glamor_pixmap_ensure_fb(pixmap); + } + + return 0; } - -enum glamor_pixmap_status + +enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap) { - GLenum format, type; - int no_alpha, no_revert; + GLenum format, type; + int no_alpha, no_revert; - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &no_revert)) { - glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); - return GLAMOR_UPLOAD_FAILED; - } - if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) - 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, no_alpha, no_revert, 1); - return GLAMOR_UPLOAD_DONE; + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + glamor_fallback("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + return GLAMOR_UPLOAD_FAILED; + } + if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) + 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, no_alpha, + no_revert, 1); + return GLAMOR_UPLOAD_DONE; } #if 0 -enum glamor_pixmap_status +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); + 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; + 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 no_alpha, no_revert; + GLenum format, type; + int no_alpha, no_revert; - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &no_revert)) { - ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); - assert(0); - } + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + ErrorF("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + assert(0); + } - in_restore = 1; - _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, no_revert, 1); - in_restore = 0; + in_restore = 1; + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, + no_revert, 1); + in_restore = 0; } /* @@ -497,77 +541,82 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap) * */ PixmapPtr -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, - GLenum *type, int no_alpha, int no_revert) +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, + GLenum * type, int no_alpha, int no_revert) { - glamor_pixmap_private *source_priv; - glamor_screen_private *glamor_priv; - ScreenPtr screen; - PixmapPtr temp_pixmap; - glamor_pixmap_private *temp_pixmap_priv; - glamor_gl_dispatch *dispatch; - static float vertices[8] = {-1, -1, - 1, -1, - 1, 1, - -1, 1}; - static float texcoords[8] = {0, 0, - 1, 0, - 1, 1, - 0, 1}; + glamor_pixmap_private *source_priv; + glamor_screen_private *glamor_priv; + ScreenPtr screen; + PixmapPtr temp_pixmap; + glamor_pixmap_private *temp_pixmap_priv; + glamor_gl_dispatch *dispatch; + static float vertices[8] = { -1, -1, + 1, -1, + 1, 1, + -1, 1 + }; + static float texcoords[8] = { 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; - int swap_rb = 0; + int swap_rb = 0; - screen = source->drawable.pScreen; + screen = source->drawable.pScreen; - glamor_priv = glamor_get_screen_private(screen); - source_priv = glamor_get_pixmap_private(source); - dispatch = &glamor_priv->dispatch; - if (*format == GL_BGRA) { - *format = GL_RGBA; - swap_rb = 1; - } + glamor_priv = glamor_get_screen_private(screen); + source_priv = glamor_get_pixmap_private(source); + dispatch = &glamor_priv->dispatch; + if (*format == GL_BGRA) { + *format = GL_RGBA; + swap_rb = 1; + } - temp_pixmap = (*screen->CreatePixmap)(screen, - source->drawable.width, - source->drawable.height, - source->drawable.depth, - 0); + temp_pixmap = (*screen->CreatePixmap) (screen, + source->drawable.width, + source->drawable.height, + source->drawable.depth, 0); - temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, source->drawable.width, - source->drawable.height, 0, - *format, *type, NULL); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, + source->drawable.width, + source->drawable.height, 0, *format, *type, + NULL); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - return temp_pixmap; + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv-> + finish_access_no_revert[no_alpha], + no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], + swap_rb); + + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + return temp_pixmap; } - + /** * Move a pixmap to CPU memory. @@ -579,174 +628,194 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, * Otherwise return FALSE. **/ -Bool +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 no_alpha, no_revert; - uint8_t *data = NULL, *read; - PixmapPtr temp_pixmap = NULL; - ScreenPtr screen; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - - screen = pixmap->drawable.pScreen; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return TRUE; - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &no_revert)) { - ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); - assert(0); // Should never happen. - return FALSE; - } + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + unsigned int stride, row_length, y; + GLenum format, type, gl_access, gl_usage; + int no_alpha, no_revert; + uint8_t *data = NULL, *read; + PixmapPtr temp_pixmap = NULL; + ScreenPtr screen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - pixmap_priv->access_mode = access; - 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); + screen = pixmap->drawable.pScreen; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return TRUE; + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + ErrorF("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + assert(0); // Should never happen. + return FALSE; + } - stride = pixmap->devKind; + pixmap_priv->access_mode = access; + 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); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - /* XXX we may don't need to validate it on GPU here, - * we can just validate it on CPU. */ - glamor_validate_pixmap(pixmap); - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) || no_revert != 1)) { - - temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, &type, no_alpha, no_revert); + stride = pixmap->devKind; - } - switch (access) { - case GLAMOR_ACCESS_RO: - gl_access = GL_READ_ONLY; - gl_usage = GL_STREAM_READ; - break; - case GLAMOR_ACCESS_WO: - data = malloc(stride * pixmap->drawable.height); - goto done; - break; - case GLAMOR_ACCESS_RW: - gl_access = GL_READ_WRITE; - gl_usage = GL_DYNAMIC_DRAW; - break; - default: - ErrorF("Glamor: Invalid access code. %d\n", access); - assert(0); - } - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - data = malloc(stride * pixmap->drawable.height); - } - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + /* XXX we may don't need to validate it on GPU here, + * we can just validate it on CPU. */ + glamor_validate_pixmap(pixmap); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); - } - else { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); - // dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, 0); - } - if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && + ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) + || no_revert != 1)) { - if (!glamor_priv->yInverted) { - assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); - dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); - } - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (pixmap_priv->pbo == 0) - dispatch->glGenBuffers (1, &pixmap_priv->pbo); - dispatch->glBindBuffer (GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); - dispatch->glBufferData (GL_PIXEL_PACK_BUFFER, - stride * pixmap->drawable.height, - NULL, gl_usage); - dispatch->glReadPixels (0, 0, - row_length, pixmap->drawable.height, - format, type, 0); - data = dispatch->glMapBuffer (GL_PIXEL_PACK_BUFFER, gl_access); - pixmap_priv->pbo_valid = TRUE; + temp_pixmap = + glamor_es2_pixmap_read_prepare(pixmap, &format, + &type, no_alpha, + no_revert); - if (!glamor_priv->yInverted) { - assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); - dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 0); - } - dispatch->glBindBuffer (GL_PIXEL_PACK_BUFFER, 0); + } + switch (access) { + case GLAMOR_ACCESS_RO: + gl_access = GL_READ_ONLY; + gl_usage = GL_STREAM_READ; + break; + case GLAMOR_ACCESS_WO: + data = malloc(stride * pixmap->drawable.height); + goto done; + break; + case GLAMOR_ACCESS_RW: + gl_access = GL_READ_WRITE; + gl_usage = GL_DYNAMIC_DRAW; + break; + default: + ErrorF("Glamor: Invalid access code. %d\n", access); + assert(0); + } + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + data = malloc(stride * pixmap->drawable.height); + } + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - } else { - if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) - type = GL_UNSIGNED_SHORT_5_5_5_1; - dispatch->glReadPixels (0, 0, - pixmap->drawable.width, pixmap->drawable.height, - format, type, data); - } - } else { - data = malloc(stride * pixmap->drawable.height); - assert(data); - if (access != GLAMOR_ACCESS_WO) { - if (pixmap_priv->pbo == 0) - dispatch->glGenBuffers(1, &pixmap_priv->pbo); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, pixmap_priv->pbo); - dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, - stride * pixmap->drawable.height, - NULL, GL_STREAM_READ); - dispatch->glReadPixels (0, 0, row_length, pixmap->drawable.height, - format, type, 0); - read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); - - for (y = 0; y < pixmap->drawable.height; y++) - memcpy(data + y * stride, - read + (pixmap->drawable.height - y - 1) * stride, stride); - dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; - } - } + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + } else { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); + // dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, 0); + } + if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); -done: - pixmap->devPrivate.ptr = data; + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == + GLAMOR_GL_DESKTOP); + dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); + } - if (temp_pixmap) { - (*screen->DestroyPixmap)(temp_pixmap); - } + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (pixmap_priv->pbo == 0) + dispatch->glGenBuffers(1, + &pixmap_priv->pbo); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, + pixmap_priv->pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, + stride * + pixmap->drawable.height, + NULL, gl_usage); + dispatch->glReadPixels(0, 0, row_length, + pixmap->drawable.height, + format, type, 0); + data = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, + gl_access); + pixmap_priv->pbo_valid = TRUE; - return TRUE; + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == + GLAMOR_GL_DESKTOP); + dispatch->glPixelStorei + (GL_PACK_INVERT_MESA, 0); + } + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + } else { + if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) + type = GL_UNSIGNED_SHORT_5_5_5_1; + dispatch->glReadPixels(0, 0, + pixmap->drawable.width, + pixmap->drawable.height, + format, type, data); + } + } else { + data = malloc(stride * pixmap->drawable.height); + assert(data); + if (access != GLAMOR_ACCESS_WO) { + if (pixmap_priv->pbo == 0) + dispatch->glGenBuffers(1, + &pixmap_priv->pbo); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, + pixmap_priv->pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, + stride * + pixmap->drawable.height, + NULL, GL_STREAM_READ); + dispatch->glReadPixels(0, 0, row_length, + pixmap->drawable.height, + format, type, 0); + read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, + GL_READ_ONLY); + + for (y = 0; y < pixmap->drawable.height; y++) + memcpy(data + y * stride, + read + (pixmap->drawable.height - + y - 1) * stride, stride); + dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + pixmap_priv->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; + } + } + + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); + done: + pixmap->devPrivate.ptr = data; + + if (temp_pixmap) { + (*screen->DestroyPixmap) (temp_pixmap); + } + + return TRUE; } -static void +static void _glamor_destroy_upload_pixmap(PixmapPtr pixmap) { - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - assert(pixmap_priv->gl_fbo == 0); - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; + assert(pixmap_priv->gl_fbo == 0); + if (pixmap_priv->fb) + dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); + if (pixmap_priv->tex) + dispatch->glDeleteTextures(1, &pixmap_priv->tex); + if (pixmap_priv->pbo) + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); + pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; } -void glamor_destroy_upload_pixmap(PixmapPtr pixmap) +void +glamor_destroy_upload_pixmap(PixmapPtr pixmap) { - _glamor_destroy_upload_pixmap(pixmap); + _glamor_destroy_upload_pixmap(pixmap); } - diff --git a/glamor/glamor_pixmap.indent.c b/glamor/glamor_pixmap.indent.c new file mode 100644 index 000000000..f02acc746 --- /dev/null +++ b/glamor/glamor_pixmap.indent.c @@ -0,0 +1,821 @@ +#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; +} + + +static void +_glamor_pixmap_validate_filling(glamor_screen_private * glamor_priv, + glamor_pixmap_private * pixmap_priv) +{ + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + GLfloat vertices[8]; + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(glamor_priv->solid_prog); + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, pixmap_priv->pending_op.fill.color4fv); + vertices[0] = -1; + vertices[1] = -1; + vertices[2] = 1; + vertices[3] = -1; + vertices[4] = 1; + vertices[5] = 1; + vertices[6] = -1; + vertices[7] = 1; + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; +} + + +glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { + NULL, + _glamor_pixmap_validate_filling +}; + +void +glamor_pixmap_init(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; +} + +void +glamor_validate_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_validate_function_t validate_op; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + + validate_op = + glamor_priv->pixmap_validate_funcs[pixmap_priv-> + pending_op.type]; + if (validate_op) { + (*validate_op) (glamor_priv, pixmap_priv); + } +} + +void +glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) +{ + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); +#ifndef GLAMOR_GLES2 + dispatch->glMatrixMode(GL_PROJECTION); + dispatch->glLoadIdentity(); + dispatch->glMatrixMode(GL_MODELVIEW); + dispatch->glLoadIdentity(); +#endif + dispatch->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) +{ + int err; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + + err = glamor_set_destination_pixmap_priv(pixmap_priv); + return err; +} + +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(struct glamor_gl_dispatch *dispatch, unsigned char alu) +{ +#ifndef GLAMOR_GLES2 + if (alu == GXcopy) { + dispatch->glDisable(GL_COLOR_LOGIC_OP); + return; + } + dispatch->glEnable(GL_COLOR_LOGIC_OP); + switch (alu) { + case GXclear: + dispatch->glLogicOp(GL_CLEAR); + break; + case GXand: + dispatch->glLogicOp(GL_AND); + break; + case GXandReverse: + dispatch->glLogicOp(GL_AND_REVERSE); + break; + case GXandInverted: + dispatch->glLogicOp(GL_AND_INVERTED); + break; + case GXnoop: + dispatch->glLogicOp(GL_NOOP); + break; + case GXxor: + dispatch->glLogicOp(GL_XOR); + break; + case GXor: + dispatch->glLogicOp(GL_OR); + break; + case GXnor: + dispatch->glLogicOp(GL_NOR); + break; + case GXequiv: + dispatch->glLogicOp(GL_EQUIV); + break; + case GXinvert: + dispatch->glLogicOp(GL_INVERT); + break; + case GXorReverse: + dispatch->glLogicOp(GL_OR_REVERSE); + break; + case GXcopyInverted: + dispatch->glLogicOp(GL_COPY_INVERTED); + break; + case GXorInverted: + dispatch->glLogicOp(GL_OR_INVERTED); + break; + case GXnand: + dispatch->glLogicOp(GL_NAND); + break; + case GXset: + dispatch->glLogicOp(GL_SET); + break; + default: + FatalError("unknown logic op\n"); + } +#else + if (alu != GXcopy) + ErrorF("unsupported alu %x \n", alu); +#endif +} + + + + +/** + * Upload pixmap to a specified texture. + * This texture may not be the one attached to it. + **/ +int in_restore = 0; +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); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + unsigned int stride, row_length; + void *texels; + GLenum iformat; + + switch (pixmap->drawable.depth) { +#if 0 + case 8: + iformat = GL_ALPHA; + break; +#endif + case 24: + iformat = GL_RGB; + break; + default: + iformat = GL_RGBA; + break; + } + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + iformat = format; + } + + stride = pixmap->devKind; + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + } else { + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } + + if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { + texels = NULL; + dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, + pixmap_priv->pbo); + } else + texels = pixmap->devPrivate.ptr; + + dispatch->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 no_alpha, int no_revert, + int flip) +{ + + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + 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 (no_alpha == 0 && no_revert == 1 && !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. */ + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + ptexcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + dispatch->glGenTextures(1, &tex); + + __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); +#ifndef GLAMOR_GLES2 + dispatch->glEnable(GL_TEXTURE_2D); +#endif + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv-> + finish_access_no_revert[no_alpha], + no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], + 0); + + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + +#ifndef GLAMOR_GLES2 + dispatch->glDisable(GL_TEXTURE_2D); +#endif + dispatch->glUseProgram(0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDeleteTextures(1, &tex); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void +glamor_pixmap_ensure_fb(PixmapPtr pixmap) +{ + int status; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + + if (pixmap_priv->fb == 0) + dispatch->glGenFramebuffers(1, &pixmap_priv->fb); + assert(pixmap_priv->tex != 0); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, pixmap_priv->tex, + 0); + status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + const char *str; + switch (status) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + str = "incomplete attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + str = "incomplete/missing attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + str = "incomplete draw buffer"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + str = "incomplete read buffer"; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + str = "unsupported"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + str = "incomplete multiple"; + break; + default: + str = "unknown error"; + break; + } + + LogMessageVerb(X_INFO, 0, + "destination is framebuffer incomplete: %s [%#x]\n", + str, status); + assert(0); + } +} + +/* + * Prepare to upload a pixmap to texture memory. + * no_alpha equals 1 means the format needs to wire alpha to 1. + * Two condtion need to setup a fbo for a pixmap + * 1. !yInverted, we need to do flip if we are not yInverted. + * 2. no_alpha != 0, we need to wire the alpha. + * */ +static int +glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) +{ + int need_fbo; + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + + if (!glamor_check_fbo_size + (glamor_priv, 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 (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) + need_fbo = 1; + else + need_fbo = 0; + + if (pixmap_priv->tex == 0) + dispatch->glGenTextures(1, &pixmap_priv->tex); + + if (need_fbo) { + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + pixmap->drawable.width, + pixmap->drawable.height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + glamor_pixmap_ensure_fb(pixmap); + } + + return 0; +} + +enum glamor_pixmap_status +glamor_upload_pixmap_to_texture(PixmapPtr pixmap) +{ + GLenum format, type; + int no_alpha, no_revert; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + glamor_fallback("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + return GLAMOR_UPLOAD_FAILED; + } + if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) + 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, no_alpha, + no_revert, 1); + 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 no_alpha, no_revert; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + ErrorF("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + assert(0); + } + + in_restore = 1; + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, + no_revert, 1); + in_restore = 0; +} + +/* + * as gles2 only support a very small set of color format and + * type when do glReadPixel, + * Before we use glReadPixels to get back a textured pixmap, + * Use shader to convert it to a supported format and thus + * get a new temporary pixmap returned. + * */ + +PixmapPtr +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, + GLenum * type, int no_alpha, int no_revert) +{ + glamor_pixmap_private *source_priv; + glamor_screen_private *glamor_priv; + ScreenPtr screen; + PixmapPtr temp_pixmap; + glamor_pixmap_private *temp_pixmap_priv; + glamor_gl_dispatch *dispatch; + static float vertices[8] = { -1, -1, + 1, -1, + 1, 1, + -1, 1 + }; + static float texcoords[8] = { 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; + + int swap_rb = 0; + + screen = source->drawable.pScreen; + + glamor_priv = glamor_get_screen_private(screen); + source_priv = glamor_get_pixmap_private(source); + dispatch = &glamor_priv->dispatch; + if (*format == GL_BGRA) { + *format = GL_RGBA; + swap_rb = 1; + } + + + temp_pixmap = (*screen->CreatePixmap) (screen, + source->drawable.width, + source->drawable.height, + source->drawable.depth, 0); + + temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + + dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, + source->drawable.width, + source->drawable.height, 0, *format, *type, + NULL); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); + + glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); + + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv-> + finish_access_no_revert[no_alpha], + no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], + swap_rb); + + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + return temp_pixmap; +} + + +/** + * 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 no_alpha, no_revert; + uint8_t *data = NULL, *read; + PixmapPtr temp_pixmap = NULL; + ScreenPtr screen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + + screen = pixmap->drawable.pScreen; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return TRUE; + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + ErrorF("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + assert(0); // Should never happen. + return FALSE; + } + + pixmap_priv->access_mode = access; + 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; + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + /* XXX we may don't need to validate it on GPU here, + * we can just validate it on CPU. */ + glamor_validate_pixmap(pixmap); + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && + ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) + || no_revert != 1)) { + + temp_pixmap = + glamor_es2_pixmap_read_prepare(pixmap, &format, + &type, no_alpha, + no_revert); + + } + switch (access) { + case GLAMOR_ACCESS_RO: + gl_access = GL_READ_ONLY; + gl_usage = GL_STREAM_READ; + break; + case GLAMOR_ACCESS_WO: + data = malloc(stride * pixmap->drawable.height); + goto done; + break; + case GLAMOR_ACCESS_RW: + gl_access = GL_READ_WRITE; + gl_usage = GL_DYNAMIC_DRAW; + break; + default: + ErrorF("Glamor: Invalid access code. %d\n", access); + assert(0); + } + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + data = malloc(stride * pixmap->drawable.height); + } + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + } else { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); + // dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, 0); + } + if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { + + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == + GLAMOR_GL_DESKTOP); + dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); + } + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (pixmap_priv->pbo == 0) + dispatch->glGenBuffers(1, + &pixmap_priv->pbo); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, + pixmap_priv->pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, + stride * + pixmap->drawable.height, + NULL, gl_usage); + dispatch->glReadPixels(0, 0, row_length, + pixmap->drawable.height, + format, type, 0); + data = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, + gl_access); + pixmap_priv->pbo_valid = TRUE; + + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == + GLAMOR_GL_DESKTOP); + dispatch->glPixelStorei + (GL_PACK_INVERT_MESA, 0); + } + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + } else { + if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) + type = GL_UNSIGNED_SHORT_5_5_5_1; + dispatch->glReadPixels(0, 0, + pixmap->drawable.width, + pixmap->drawable.height, + format, type, data); + } + } else { + data = malloc(stride * pixmap->drawable.height); + assert(data); + if (access != GLAMOR_ACCESS_WO) { + if (pixmap_priv->pbo == 0) + dispatch->glGenBuffers(1, + &pixmap_priv->pbo); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, + pixmap_priv->pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, + stride * + pixmap->drawable.height, + NULL, GL_STREAM_READ); + dispatch->glReadPixels(0, 0, row_length, + pixmap->drawable.height, + format, type, 0); + read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, + GL_READ_ONLY); + + for (y = 0; y < pixmap->drawable.height; y++) + memcpy(data + y * stride, + read + (pixmap->drawable.height - + y - 1) * stride, stride); + dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + pixmap_priv->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); + pixmap_priv->pbo = 0; + } + } + + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); + done: + pixmap->devPrivate.ptr = data; + + if (temp_pixmap) { + (*screen->DestroyPixmap) (temp_pixmap); + } + + return TRUE; +} + + + +static void +_glamor_destroy_upload_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + + assert(pixmap_priv->gl_fbo == 0); + if (pixmap_priv->fb) + dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); + if (pixmap_priv->tex) + dispatch->glDeleteTextures(1, &pixmap_priv->tex); + if (pixmap_priv->pbo) + dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); + pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; + +} + +void +glamor_destroy_upload_pixmap(PixmapPtr pixmap) +{ + _glamor_destroy_upload_pixmap(pixmap); +} diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 3cc4b527d..762dfc255 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -39,72 +39,69 @@ void glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, - int nrect, - xRectangle *prect) + GCPtr gc, int nrect, xRectangle * prect) { - int fullX1, fullX2, fullY1, fullY2; - int xorg, yorg; - int n; - register BoxPtr pbox; - RegionPtr pClip = fbGetCompositeClip(gc); - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { - goto fail; - } + int fullX1, fullX2, fullY1, fullY2; + int xorg, yorg; + int n; + register BoxPtr pbox; - xorg = drawable->x; - yorg = drawable->y; - - while (nrect--) { - fullX1 = prect->x + xorg; - fullY1 = prect->y + yorg; - fullX2 = fullX1 + (int)prect->width; - fullY2 = fullY1 + (int)prect->height; - prect++; - - n = REGION_NUM_RECTS(pClip); - pbox = REGION_RECTS(pClip); - /* - * clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect(), - * but rectangles may overlap each other here. - */ - while (n--) { - int x1 = fullX1; - int x2 = fullX2; - int y1 = fullY1; - int y2 = fullY2; - - if (pbox->x1 > x1) - x1 = pbox->x1; - if (pbox->x2 < x2) - x2 = pbox->x2; - if (pbox->y1 > y1) - y1 = pbox->y1; - if (pbox->y2 < y2) - y2 = pbox->y2; - pbox++; - - if (x1 >= x2 || y1 >= y2) - continue; - glamor_fill(drawable, - gc, - x1, - y1, - x2 - x1, - y2 - y1); - } - } - return; - -fail: - 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 ); - glamor_finish_access_gc(gc); + RegionPtr pClip = fbGetCompositeClip(gc); + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { + goto fail; } - glamor_finish_access(drawable); - } + + xorg = drawable->x; + yorg = drawable->y; + + while (nrect--) { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int) prect->width; + fullY2 = fullY1 + (int) prect->height; + prect++; + + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + /* + * clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect(), + * but rectangles may overlap each other here. + */ + while (n--) { + int x1 = fullX1; + int x2 = fullX2; + int y1 = fullY1; + int y2 = fullY2; + + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (pbox->y1 > y1) + y1 = pbox->y1; + if (pbox->y2 < y2) + y2 = pbox->y2; + pbox++; + + if (x1 >= x2 || y1 >= y2) + continue; + if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, + y2 - y1)) + goto fail; + } + } + return; + + fail: + 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); + glamor_finish_access_gc(gc); + } + glamor_finish_access(drawable); + } + return; } diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index d93b60209..01124bbe0 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -46,134 +46,130 @@ void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points) { - xRectangle *rects; - int x1, x2, y1, y2; - int i; - int x_min = MAXSHORT; - int x_max = MINSHORT; - int y_min = MAXSHORT; - int y_max = MINSHORT; - DrawablePtr temp_dest; - PixmapPtr temp_pixmap; - GCPtr temp_gc = NULL; - /* 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. - */ - goto fail; - } - if (gc->lineStyle != LineSolid || - gc->fillStyle != FillSolid) { - glamor_fallback("non-solid fill line style %d, fill style %d\n", - gc->lineStyle, gc->fillStyle); - goto fail; - } + xRectangle *rects; + int x1, x2, y1, y2; + int i; + int x_min = MAXSHORT; + int x_max = MINSHORT; + int y_min = MAXSHORT; + int y_max = MINSHORT; + DrawablePtr temp_dest; + PixmapPtr temp_pixmap; + GCPtr temp_gc = NULL; + /* 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. + */ + goto fail; + } + if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { + glamor_fallback + ("non-solid fill line style %d, fill style %d\n", + gc->lineStyle, gc->fillStyle); + goto fail; + } - rects = malloc(sizeof(xRectangle) * (n - 1)); - x1 = points[0].x; - y1 = points[0].y; - /* If we have any non-horizontal/vertical, fall back. */ - for (i = 0; i < n - 1; i++) { - if (mode == CoordModePrevious) { - x2 = x1 + points[i + 1].x; - y2 = y1 + points[i + 1].y; + rects = malloc(sizeof(xRectangle) * (n - 1)); + x1 = points[0].x; + y1 = points[0].y; + /* If we have any non-horizontal/vertical, fall back. */ + for (i = 0; i < n - 1; i++) { + if (mode == CoordModePrevious) { + x2 = x1 + points[i + 1].x; + y2 = y1 + points[i + 1].y; + } else { + x2 = points[i + 1].x; + y2 = points[i + 1].y; + } + if (x1 != x2 && y1 != y2) { + free(rects); + glamor_fallback("stub diagonal poly_line\n"); + goto fail; + } + if (x1 < x2) { + rects[i].x = x1; + rects[i].width = x2 - x1 + 1; + } else { + rects[i].x = x2; + rects[i].width = x1 - x2 + 1; + } + if (y1 < y2) { + rects[i].y = y1; + rects[i].height = y2 - y1 + 1; + } else { + rects[i].y = y2; + rects[i].height = y1 - y2 + 1; + } + + x1 = x2; + y1 = y2; + } + gc->ops->PolyFillRect(drawable, gc, n - 1, rects); + free(rects); + return; + + fail: + for (i = 0; i < n; i++) { + if (x_min > points[i].x) + x_min = points[i].x; + if (x_max < points[i].x) + x_max = points[i].x; + + if (y_min > points[i].y) + y_min = points[i].y; + if (y_max < points[i].y) + y_max = points[i].y; + } + + temp_pixmap = drawable->pScreen->CreatePixmap(drawable->pScreen, + x_max - x_min + 1, + y_max - y_min + 1, + drawable->depth, 0); + if (temp_pixmap) { + temp_dest = &temp_pixmap->drawable; + temp_gc = + GetScratchGC(temp_dest->depth, temp_dest->pScreen); + ValidateGC(temp_dest, temp_gc); + for (i = 0; i < n; i++) { + points[i].x -= x_min; + points[i].y -= y_min; + } + (void) glamor_copy_area(drawable, + temp_dest, + temp_gc, + x_min, y_min, + x_max - x_min + 1, + y_max - y_min + 1, 0, 0); + + } else + temp_dest = drawable; + + if (gc->lineWidth == 0) { + if (glamor_prepare_access(temp_dest, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access_gc(gc)) { + fbPolyLine(temp_dest, gc, mode, n, points); + glamor_finish_access_gc(gc); + } + glamor_finish_access(temp_dest); + } } else { - x2 = points[i + 1].x; - y2 = points[i + 1].y; + /* fb calls mi functions in the lineWidth != 0 case. */ + fbPolyLine(drawable, gc, mode, n, points); } - if (x1 != x2 && y1 != y2) { - free(rects); - glamor_fallback("stub diagonal poly_line\n"); - goto fail; + if (temp_dest != drawable) { + (void) glamor_copy_area(temp_dest, + drawable, + temp_gc, + 0, 0, + x_max - x_min + 1, + y_max - y_min + 1, x_min, y_min); + drawable->pScreen->DestroyPixmap(temp_pixmap); + for (i = 0; i < n; i++) { + points[i].x += x_min; + points[i].y += y_min; + } + + FreeScratchGC(temp_gc); } - if (x1 < x2) { - rects[i].x = x1; - rects[i].width = x2 - x1 + 1; - } else { - rects[i].x = x2; - rects[i].width = x1 - x2 + 1; - } - if (y1 < y2) { - rects[i].y = y1; - rects[i].height = y2 - y1 + 1; - } else { - rects[i].y = y2; - rects[i].height = y1 - y2 + 1; - } - - x1 = x2; - y1 = y2; - } - gc->ops->PolyFillRect(drawable, gc, n - 1, rects); - free(rects); - return; - -fail: - for(i = 0; i < n; i++) - { - if (x_min > points[i].x) - x_min = points[i].x; - if (x_max < points[i].x) - x_max = points[i].x; - - if (y_min > points[i].y) - y_min = points[i].y; - if (y_max < points[i].y) - y_max = points[i].y; - } - - temp_pixmap = drawable->pScreen->CreatePixmap(drawable->pScreen, - x_max - x_min + 1, y_max - y_min + 1, - drawable->depth, - 0); - if (temp_pixmap) { - temp_dest = &temp_pixmap->drawable; - temp_gc = GetScratchGC(temp_dest->depth, temp_dest->pScreen); - ValidateGC(temp_dest, temp_gc); - for(i = 0; i < n; i++) - { - points[i].x -= x_min; - points[i].y -= y_min; - } - (void)glamor_copy_area(drawable, - temp_dest, - temp_gc, - x_min, y_min, - x_max - x_min + 1, y_max - y_min + 1, - 0, 0); - - } - else - temp_dest = drawable; - - if (gc->lineWidth == 0) { - if (glamor_prepare_access(temp_dest, GLAMOR_ACCESS_RW)) { - if (glamor_prepare_access_gc(gc)) { - fbPolyLine(temp_dest, gc, mode, n, points); - glamor_finish_access_gc(gc); - } - glamor_finish_access(temp_dest); - } - } - else { - /* fb calls mi functions in the lineWidth != 0 case. */ - fbPolyLine(drawable, gc, mode, n, points); - } - if (temp_dest != drawable) { - (void)glamor_copy_area(temp_dest, - drawable, - temp_gc, - 0, 0, - x_max - x_min + 1, y_max - y_min + 1, - x_min, y_min); - drawable->pScreen->DestroyPixmap(temp_pixmap); - for(i = 0; i < n; i++) - { - points[i].x += x_min; - points[i].y += y_min; - } - - FreeScratchGC(temp_gc); - } } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 5f82c7883..66c43591d 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -31,7 +31,7 @@ #include #include #endif - +#include #include "glamor.h" @@ -41,7 +41,7 @@ #include #include -#define GLAMOR_DEFAULT_PRECISION "precision mediump float;\n" +#define GLAMOR_DEFAULT_PRECISION "precision mediump float;\n" #include "glamor_glext.h" #else #include @@ -56,63 +56,66 @@ #include "glamor_debug.h" 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; enum glamor_vertex_type { - GLAMOR_VERTEX_POS, - GLAMOR_VERTEX_SOURCE, - GLAMOR_VERTEX_MASK + GLAMOR_VERTEX_POS, + GLAMOR_VERTEX_SOURCE, + GLAMOR_VERTEX_MASK }; 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, }; struct glamor_screen_private; struct glamor_pixmap_private; -typedef void (*glamor_pixmap_validate_function_t)(struct glamor_screen_private*, - struct glamor_pixmap_private*); +typedef void (*glamor_pixmap_validate_function_t) (struct + glamor_screen_private *, + struct + glamor_pixmap_private + *); enum glamor_gl_flavor { - GLAMOR_GL_DESKTOP, // OPENGL API - GLAMOR_GL_ES2 // OPENGL ES2.0 API + GLAMOR_GL_DESKTOP, // OPENGL API + GLAMOR_GL_ES2 // OPENGL ES2.0 API }; #define GLAMOR_CREATE_PIXMAP_CPU 0x100 @@ -121,98 +124,97 @@ enum glamor_gl_flavor { #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 typedef struct { - PicturePtr picture; /* Where the glyphs of the cache are stored */ - GlyphPtr *glyphs; - uint16_t count; - uint16_t evict; + PicturePtr picture; /* Where the glyphs of the cache are stored */ + GlyphPtr *glyphs; + uint16_t count; + uint16_t evict; } glamor_glyph_cache_t; #include "glamor_gl_dispatch.h" 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; - CreatePictureProcPtr saved_create_picture; - DestroyPictureProcPtr saved_destroy_picture; - UnrealizeGlyphProcPtr saved_unrealize_glyph; + 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; + UnrealizeGlyphProcPtr saved_unrealize_glyph; - int yInverted; - int screen_fbo; - GLuint vbo; - int vbo_offset; - int vbo_size; - char *vb; - int vb_stride; - enum glamor_gl_flavor gl_flavor; - int has_pack_invert; - int has_fbo_blit; - int max_fbo_size; + int yInverted; + int screen_fbo; + GLuint vbo; + int vbo_offset; + int vbo_size; + char *vb; + int vb_stride; + enum glamor_gl_flavor gl_flavor; + int has_pack_invert; + int has_fbo_blit; + int max_fbo_size; - /* glamor_finishaccess */ - GLint finish_access_prog[2]; - GLint finish_access_no_revert[2]; - GLint finish_access_swap_rb[2]; + /* glamor_finishaccess */ + GLint finish_access_prog[2]; + GLint finish_access_no_revert[2]; + GLint finish_access_swap_rb[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; - GLint put_image_xybitmap_fg_uniform_location; - GLint put_image_xybitmap_bg_uniform_location; + /* glamor_putimage */ + GLint put_image_xybitmap_prog; + 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_pixmap_validate_function_t *pixmap_validate_funcs; - glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; - char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; - int delayed_fallback_pending; + /* 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_pixmap_validate_function_t *pixmap_validate_funcs; + glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; + char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; + int delayed_fallback_pending; - glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; - Bool glyph_cache_initialized; - struct glamor_gl_dispatch dispatch; + glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; + Bool glyph_cache_initialized; + struct glamor_gl_dispatch dispatch; } glamor_screen_private; typedef enum glamor_access { - GLAMOR_ACCESS_RO, - GLAMOR_ACCESS_RW, - GLAMOR_ACCESS_WO, + GLAMOR_ACCESS_RO, + GLAMOR_ACCESS_RW, + GLAMOR_ACCESS_WO, } glamor_access_t; -enum _glamor_pending_op_type{ - GLAMOR_PENDING_NONE, - GLAMOR_PENDING_FILL +enum _glamor_pending_op_type { + GLAMOR_PENDING_NONE, + GLAMOR_PENDING_FILL }; typedef struct _glamor_pending_fill { - unsigned int type; - GLfloat color4fv[4]; - CARD32 colori; + unsigned int type; + GLfloat color4fv[4]; + CARD32 colori; } glamor_pending_fill; typedef union _glamor_pending_op { - unsigned int type; - glamor_pending_fill fill; + unsigned int type; + glamor_pending_fill fill; } glamor_pending_op; /* @@ -231,18 +233,18 @@ typedef union _glamor_pending_op { **/ typedef struct glamor_pixmap_private { - 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; - glamor_pending_op pending_op; - PixmapPtr container; - glamor_screen_private *glamor_priv; + 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; + glamor_pending_op pending_op; + PixmapPtr container; + glamor_screen_private *glamor_priv; } glamor_pixmap_private; /* @@ -255,11 +257,11 @@ typedef struct glamor_pixmap_private { * * */ typedef enum glamor_pixmap_status { - GLAMOR_NONE, - GLAMOR_UPLOAD_PENDING, - GLAMOR_UPLOAD_DONE, - GLAMOR_UPLOAD_FAILED -} glamor_pixmap_status_t; + GLAMOR_NONE, + GLAMOR_UPLOAD_PENDING, + GLAMOR_UPLOAD_DONE, + GLAMOR_UPLOAD_FAILED +} glamor_pixmap_status_t; extern DevPrivateKey glamor_screen_private_key; @@ -267,13 +269,16 @@ 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); } @@ -284,8 +289,8 @@ 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); } extern int glamor_debug_level; @@ -299,19 +304,11 @@ Bool glamor_close_screen(int idx, ScreenPtr screen); /* glamor_copyarea.c */ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, - int srcx, int srcy, int width, int height, int dstx, int dsty); -void -glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, - Pixel bitplane, - void *closure); + int srcx, int srcy, int width, int height, int dstx, + int dsty); +void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, + BoxPtr box, int nbox, int dx, int dy, Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure); /* glamor_copywindow.c */ void glamor_copy_window(WindowPtr win, DDXPointRec old_origin, @@ -334,30 +331,35 @@ Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, unsigned char alu, unsigned long planemask, unsigned long fg_pixel, unsigned long bg_pixel, int stipple_x, int stipple_y); -GLint glamor_compile_glsl_prog(glamor_gl_dispatch *dispatch, GLenum type, const char *source); -void glamor_link_glsl_prog(glamor_gl_dispatch *dispatch, GLint prog); -void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, unsigned long fg_pixel, - GLfloat *color); +GLint glamor_compile_glsl_prog(glamor_gl_dispatch * dispatch, GLenum type, + const char *source); +void glamor_link_glsl_prog(glamor_gl_dispatch * dispatch, GLint prog); +void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, + unsigned long fg_pixel, + GLfloat * color); int glamor_set_destination_pixmap(PixmapPtr pixmap); -int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv); +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_destination_pixmap_priv_nc(glamor_pixmap_private * + pixmap_priv); PixmapPtr -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, - GLenum *type, int no_alpha, int no_revert); +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, + GLenum * type, int no_alpha, int no_revert); -void glamor_set_alu(struct glamor_gl_dispatch * dispatch, unsigned char alu); +void glamor_set_alu(struct glamor_gl_dispatch *dispatch, + unsigned char alu); Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); Bool glamor_gl_has_extension(char *extension); -int glamor_gl_get_version(void); +int glamor_gl_get_version(void); #define GLAMOR_GL_VERSION_ENCODE(major, minor) ( \ ((major) * 256) \ @@ -367,12 +369,8 @@ int glamor_gl_get_version(void); /* glamor_fill.c */ -void glamor_fill(DrawablePtr drawable, - GCPtr gc, - int x, - int y, - int width, - int height); +Bool glamor_fill(DrawablePtr drawable, + GCPtr gc, int x, int y, int width, int height); Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel); @@ -381,22 +379,18 @@ void glamor_solid_fail_region(PixmapPtr pixmap, /* glamor_fillspans.c */ void glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, - int n, - DDXPointPtr points, - int *widths, - int sorted); + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted); void glamor_init_solid_shader(ScreenPtr screen); /* glamor_getspans.c */ void + glamor_get_spans(DrawablePtr drawable, int wmax, DDXPointPtr points, - int *widths, - int nspans, - char *dst_start); + int *widths, int nspans, char *dst_start); /* glamor_glyphs.c */ void glamor_glyphs_fini(ScreenPtr screen); @@ -405,10 +399,10 @@ void glamor_glyphs(CARD8 op, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); + INT16 ySrc, int nlist, GlyphListPtr list, + GlyphPtr * glyphs); -void -glamor_glyph_unrealize (ScreenPtr screen, GlyphPtr glyph); +void glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph); /* glamor_setspans.c */ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted); @@ -416,17 +410,17 @@ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, /* glamor_polyfillrect.c */ void glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, - int nrect, - xRectangle *prect); + GCPtr gc, int nrect, xRectangle * prect); /* glamor_polylines.c */ void + glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points); /* glamor_putimage.c */ void + glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits); void glamor_init_putimage_shaders(ScreenPtr screen); @@ -440,18 +434,16 @@ void glamor_composite(CARD8 op, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); void glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid *traps); + int ntrap, xTrapezoid * traps); void glamor_init_composite_shaders(ScreenPtr screen); void glamor_composite_rects(CARD8 op, - PicturePtr src, PicturePtr mask, PicturePtr dst, - int nrect, glamor_composite_rect_t *rects); + PicturePtr src, PicturePtr mask, + PicturePtr dst, int nrect, + glamor_composite_rect_t * rects); /* glamor_tile.c */ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, @@ -462,19 +454,16 @@ void glamor_init_tile_shader(ScreenPtr screen); /* glamor_triangles.c */ void -glamor_triangles (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int ntris, - xTriangle *tris); + +glamor_triangles(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris); /* glamor_pixmap.c */ -void -glamor_pixmap_init(ScreenPtr screen); +void glamor_pixmap_init(ScreenPtr screen); /** * Download a pixmap's texture to cpu memory. If success, * One copy of current pixmap's texture will be put into @@ -484,8 +473,8 @@ glamor_pixmap_init(ScreenPtr screen); * gl_tex must be 1. Used by glamor_prepare_access. * */ -Bool -glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access); +Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, + glamor_access_t access); /** * Restore a pixmap's data which is downloaded by @@ -496,8 +485,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access); * in texture originally. In other word, the gl_fbo * must be 1. **/ -void -glamor_restore_pixmap_to_texture(PixmapPtr pixmap); +void glamor_restore_pixmap_to_texture(PixmapPtr pixmap); /** * Ensure to have a fbo attached to the pixmap. * If the pixmap already has one fbo then do nothing. @@ -506,53 +494,49 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap); * The pixmap must has a valid texture before call this * API, othersie, it will trigger a assert. */ -void -glamor_pixmap_ensure_fb(PixmapPtr pixmap); +void glamor_pixmap_ensure_fb(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); +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); +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); +void glamor_destroy_upload_pixmap(PixmapPtr pixmap); -void -glamor_validate_pixmap(PixmapPtr pixmap); +void glamor_validate_pixmap(PixmapPtr pixmap); -int -glamor_create_picture(PicturePtr picture); +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_finish_access_picture(PicturePtr picture); + +void glamor_destroy_picture(PicturePtr picture); + +enum glamor_pixmap_status + glamor_upload_picture_to_texture(PicturePtr picture); void -glamor_destroy_picture(PicturePtr picture); -enum glamor_pixmap_status -glamor_upload_picture_to_texture(PicturePtr picture); +glamor_picture_format_fixup(PicturePtr picture, + glamor_pixmap_private * pixmap_priv); -void -glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_priv); - -#include"glamor_utils.h" +#include"glamor_utils.h" /* Dynamic pixmap upload to texture if needed. * Sometimes, the target is a gl texture pixmap/picture, @@ -561,9 +545,9 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr * fallback the whole process to cpu. Most of the time, * this will increase performance obviously. */ -#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -#define GLAMOR_DELAYED_FILLING +#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD +//#define GLAMOR_DELAYED_FILLING -#endif /* GLAMOR_PRIV_H */ +#endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index cdcde5e7e..a8cafed52 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -36,56 +36,50 @@ void glamor_init_putimage_shaders(ScreenPtr screen) { #if 0 - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - const char *xybitmap_vs = - "uniform float x_bias;\n" - "uniform float x_scale;\n" - "uniform float y_bias;\n" - "uniform float y_scale;\n" - "varying vec2 bitmap_coords;\n" - "void main()\n" - "{\n" - " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" - " (gl_Vertex.y + y_bias) * y_scale,\n" - " 0,\n" - " 1);\n" - " bitmap_coords = gl_MultiTexCoord0.xy;\n" - "}\n"; - const char *xybitmap_fs = - "uniform vec4 fg, bg;\n" - "varying vec2 bitmap_coords;\n" - "uniform sampler2D bitmap_sampler;\n" - "void main()\n" - "{\n" - " float bitmap_value = texture2D(bitmap_sampler,\n" - " bitmap_coords).x;\n" - " gl_FragColor = mix(bg, fg, bitmap_value);\n" - "}\n"; - GLint fs_prog, vs_prog, prog; - GLint sampler_uniform_location; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + const char *xybitmap_vs = + "uniform float x_bias;\n" "uniform float x_scale;\n" + "uniform float y_bias;\n" "uniform float y_scale;\n" + "varying vec2 bitmap_coords;\n" "void main()\n" "{\n" + " gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n" + " (gl_Vertex.y + y_bias) * y_scale,\n" + " 0,\n" + " 1);\n" + " bitmap_coords = gl_MultiTexCoord0.xy;\n" "}\n"; + const char *xybitmap_fs = + "uniform vec4 fg, bg;\n" "varying vec2 bitmap_coords;\n" + "uniform sampler2D bitmap_sampler;\n" "void main()\n" "{\n" + " float bitmap_value = texture2D(bitmap_sampler,\n" + " bitmap_coords).x;\n" + " gl_FragColor = mix(bg, fg, bitmap_value);\n" "}\n"; + GLint fs_prog, vs_prog, prog; + GLint sampler_uniform_location; - if (!GLEW_ARB_fragment_shader) - return; + if (!GLEW_ARB_fragment_shader) + return; - prog = dispatch->glCreateProgram(); - vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xybitmap_vs); - fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xybitmap_fs); - dispatch->glAttachShader(prog, vs_prog); - dispatch->glAttachShader(prog, fs_prog); - glamor_link_glsl_prog(prog); + prog = dispatch->glCreateProgram(); + vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xybitmap_vs); + fs_prog = + glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xybitmap_fs); + dispatch->glAttachShader(prog, vs_prog); + dispatch->glAttachShader(prog, fs_prog); + glamor_link_glsl_prog(prog); - dispatch->glUseProgram(prog); - sampler_uniform_location = dispatch->glGetUniformLocation(prog, "bitmap_sampler"); - dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUseProgram(prog); + sampler_uniform_location = + dispatch->glGetUniformLocation(prog, "bitmap_sampler"); + dispatch->glUniform1i(sampler_uniform_location, 0); - glamor_priv->put_image_xybitmap_fg_uniform_location = - dispatch->glGetUniformLocation(prog, "fg"); - glamor_priv->put_image_xybitmap_bg_uniform_location = - dispatch->glGetUniformLocation(prog, "bg"); - glamor_get_transform_uniform_locations(prog, - &glamor_priv->put_image_xybitmap_transform); - glamor_priv->put_image_xybitmap_prog = prog; - dispatch->glUseProgram(0); + glamor_priv->put_image_xybitmap_fg_uniform_location = + dispatch->glGetUniformLocation(prog, "fg"); + glamor_priv->put_image_xybitmap_bg_uniform_location = + dispatch->glGetUniformLocation(prog, "bg"); + glamor_get_transform_uniform_locations(prog, + &glamor_priv->put_image_xybitmap_transform); + glamor_priv->put_image_xybitmap_prog = prog; + dispatch->glUseProgram(0); #endif } @@ -106,13 +100,13 @@ glamor_init_putimage_shaders(ScreenPtr screen) static int y_flip(PixmapPtr pixmap, int y) { - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); + ScreenPtr screen = pixmap->drawable.pScreen; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); - if (pixmap == screen_pixmap) - return (pixmap->drawable.height - 1) - y; - else - return y; + if (pixmap == screen_pixmap) + return (pixmap->drawable.height - 1) - y; + else + return y; } @@ -121,129 +115,127 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, int x, int y, int w, int h, int left_pad, int image_format, char *bits) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - float fg[4], bg[4]; - GLuint tex; - unsigned int stride = PixmapBytePad(1, w + left_pad); - RegionPtr clip; - BoxPtr box; - int nbox; - float dest_coords[8]; - const float bitmap_coords[8] = { - 0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - 0.0, 1.0, - }; - GLfloat xscale, yscale; - glamor_pixmap_private *pixmap_priv; - - pixmap_priv = glamor_get_pixmap_private(pixmap); + ScreenPtr screen = drawable->pScreen; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + float fg[4], bg[4]; + GLuint tex; + unsigned int stride = PixmapBytePad(1, w + left_pad); + RegionPtr clip; + BoxPtr box; + int nbox; + float dest_coords[8]; + const float bitmap_coords[8] = { + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 0.0, 1.0, + }; + GLfloat xscale, yscale; + glamor_pixmap_private *pixmap_priv; - pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_set_normalize_vcoords(xscale, yscale, - x, y, - x + w, y + h, - glamor_priv->yInverted, - dest_coords); + pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); - glamor_fallback("glamor_put_image_xybitmap: disabled\n"); - goto fail; + glamor_set_normalize_vcoords(xscale, yscale, + x, y, + x + w, y + h, + glamor_priv->yInverted, dest_coords); - if (glamor_priv->put_image_xybitmap_prog == 0) { - ErrorF("no program for xybitmap putimage\n"); - goto fail; - } - - glamor_set_alu(gc->alu); - if (!glamor_set_planemask(pixmap, gc->planemask)) + glamor_fallback("glamor_put_image_xybitmap: disabled\n"); goto fail; - dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog); + if (glamor_priv->put_image_xybitmap_prog == 0) { + ErrorF("no program for xybitmap putimage\n"); + goto fail; + } - glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); - dispatch->glUniform4fv(glamor_priv->put_image_xybitmap_fg_uniform_location, - 1, fg); - glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); - dispatch->glUniform4fv(glamor_priv->put_image_xybitmap_bg_uniform_location, - 1, bg); + glamor_set_alu(gc->alu); + if (!glamor_set_planemask(pixmap, gc->planemask)) + goto fail; - dispatch->glGenTextures(1, &tex); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glEnable(GL_TEXTURE_2D); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); - dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, - w, h, 0, - GL_COLOR_INDEX, GL_BITMAP, bits); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog); - /* Now that we've set up our bitmap texture and the shader, shove - * the destination rectangle through the cliprects and run the - * shader on the resulting fragments. - */ - dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords); - dispatch->glEnableClientState(GL_VERTEX_ARRAY); - dispatch->glClientActiveTexture(GL_TEXTURE0); - dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); - dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); + dispatch->glUniform4fv + (glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg); + glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); + dispatch->glUniform4fv + (glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); - dispatch->glEnable(GL_SCISSOR_TEST); - clip = fbGetCompositeClip(gc); - for (nbox = REGION_NUM_RECTS(clip), - box = REGION_RECTS(clip); - nbox--; - box++) - { - int x1 = x; - int y1 = y; - int x2 = x + w; - int y2 = y + h; + dispatch->glGenTextures(1, &tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); + dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, + w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + dispatch->glEnable(GL_TEXTURE_2D); - if (x1 < box->x1) - x1 = box->x1; - if (y1 < box->y1) - y1 = box->y1; - if (x2 > box->x2) - x2 = box->x2; - if (y2 > box->y2) - y2 = box->y2; - if (x1 >= x2 || y1 >= y2) - continue; + /* Now that we've set up our bitmap texture and the shader, shove + * the destination rectangle through the cliprects and run the + * shader on the resulting fragments. + */ + dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords); + dispatch->glEnableClientState(GL_VERTEX_ARRAY); + dispatch->glClientActiveTexture(GL_TEXTURE0); + dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); + dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY); - dispatch->glScissor(box->x1, - y_flip(pixmap, box->y1), - box->x2 - box->x1, - box->y2 - box->y1); - dispatch->glDrawArrays(GL_QUADS, 0, 4); - } + dispatch->glEnable(GL_SCISSOR_TEST); + clip = fbGetCompositeClip(gc); + for (nbox = REGION_NUM_RECTS(clip), + box = REGION_RECTS(clip); nbox--; box++) { + int x1 = x; + int y1 = y; + int x2 = x + w; + int y2 = y + h; - dispatch->glDisable(GL_SCISSOR_TEST); - glamor_set_alu(GXcopy); - glamor_set_planemask(pixmap, ~0); - dispatch->glDeleteTextures(1, &tex); - dispatch->glDisable(GL_TEXTURE_2D); - dispatch->glDisableClientState(GL_VERTEX_ARRAY); - dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY); - return; - glamor_set_alu(GXcopy); - glamor_set_planemask(pixmap, ~0); - 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); - } + if (x1 < box->x1) + x1 = box->x1; + if (y1 < box->y1) + y1 = box->y1; + if (x2 > box->x2) + x2 = box->x2; + if (y2 > box->y2) + y2 = box->y2; + if (x1 >= x2 || y1 >= y2) + continue; + + dispatch->glScissor(box->x1, + y_flip(pixmap, box->y1), + box->x2 - box->x1, box->y2 - box->y1); + dispatch->glDrawArrays(GL_QUADS, 0, 4); + } + + dispatch->glDisable(GL_SCISSOR_TEST); + glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); + dispatch->glDeleteTextures(1, &tex); + dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisableClientState(GL_VERTEX_ARRAY); + dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY); + return; + glamor_set_alu(GXcopy); + glamor_set_planemask(pixmap, ~0); + 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); + } } #endif @@ -252,166 +244,162 @@ void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int left_pad, int image_format, char *bits) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - GLenum type, format, iformat; - RegionPtr clip; - BoxPtr pbox; - int nbox; - int src_stride = PixmapBytePad(w, drawable->depth); - int x_off, y_off; - float vertices[8], texcoords[8]; - GLfloat xscale, yscale, txscale, tyscale; - GLuint tex; - int no_alpha, no_revert; - if (image_format == XYBitmap) { - assert(depth == 1); - goto fail; - return; - } + glamor_screen_private *glamor_priv = + glamor_get_screen_private(drawable->pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + GLenum type, format, iformat; + RegionPtr clip; + BoxPtr pbox; + int nbox; + int src_stride = PixmapBytePad(w, drawable->depth); + int x_off, y_off; + float vertices[8], texcoords[8]; + GLfloat xscale, yscale, txscale, tyscale; + GLuint tex; + int no_alpha, no_revert; + if (image_format == XYBitmap) { + assert(depth == 1); + goto fail; + return; + } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("has no fbo.\n"); - goto fail; - } + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("has no fbo.\n"); + goto fail; + } - if (image_format != ZPixmap) { - glamor_fallback("non-ZPixmap\n"); - goto fail; - } + if (image_format != ZPixmap) { + glamor_fallback("non-ZPixmap\n"); + goto fail; + } - if (!glamor_set_planemask(pixmap, gc->planemask)) { - goto fail; - } - glamor_set_alu(dispatch, gc->alu); + if (!glamor_set_planemask(pixmap, gc->planemask)) { + goto fail; + } + glamor_set_alu(dispatch, gc->alu); - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &no_revert - )) { - glamor_fallback("unknown depth. %d \n", - drawable->depth); - goto fail; - } + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + glamor_fallback("unknown depth. %d \n", drawable->depth); + goto fail; + } - /* XXX consider to reuse a function to do the following work. */ - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + /* XXX consider to reuse a function to do the following work. */ + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, src_stride * 8 / - pixmap->drawable.bitsPerPixel); - } - else { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, + src_stride * 8 / + pixmap->drawable.bitsPerPixel); + } else { + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - } - - dispatch->glGenTextures(1, &tex); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - iformat = format; - } - else { - iformat = GL_RGBA; - } + } - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, - w, h, 0, - format, type, bits); + dispatch->glGenTextures(1, &tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + iformat = format; + } else { + iformat = GL_RGBA; + } - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, + w, h, 0, format, type, bits); + + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], 0); + dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUniform1i(glamor_priv-> + finish_access_no_revert[no_alpha], + no_revert); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], + 0); - x += drawable->x; - y += drawable->y; + x += drawable->x; + y += drawable->y; - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - clip = fbGetCompositeClip(gc); + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + clip = fbGetCompositeClip(gc); - txscale = 1.0/w; - tyscale = 1.0/h; - pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + txscale = 1.0 / w; + tyscale = 1.0 / h; + pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); - for (nbox = REGION_NUM_RECTS(clip), - pbox = REGION_RECTS(clip); - nbox--; - pbox++) - { - int x1 = x; - int y1 = y; - int x2 = x + w; - int y2 = y + h; + for (nbox = REGION_NUM_RECTS(clip), + pbox = REGION_RECTS(clip); nbox--; pbox++) { + int x1 = x; + int y1 = y; + int x2 = x + w; + int y2 = y + h; - if (x1 < pbox->x1) - x1 = pbox->x1; - if (y1 < pbox->y1) - y1 = pbox->y1; - if (x2 > pbox->x2) - x2 = pbox->x2; - if (y2 > pbox->y2) - y2 = pbox->y2; - if (x1 >= x2 || y1 >= y2) - continue; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; - glamor_set_normalize_tcoords( txscale, tyscale, - x1 - x, y1 - y, - x2 - x, y2 - y, - 1, - texcoords); + glamor_set_normalize_tcoords(txscale, tyscale, + x1 - x, y1 - y, + x2 - x, y2 - y, 1, texcoords); - glamor_set_normalize_vcoords( xscale, yscale, - x1 + x_off, y1 + y_off, - x2 + x_off, y2 + y_off, - glamor_priv->yInverted, - vertices); + glamor_set_normalize_vcoords(xscale, yscale, + x1 + x_off, y1 + y_off, + x2 + x_off, y2 + y_off, + glamor_priv->yInverted, + vertices); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } #ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glDeleteTextures(1, &tex); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(pixmap, ~0); - return; + dispatch->glUseProgram(0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDeleteTextures(1, &tex); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glamor_set_alu(dispatch, GXcopy); + glamor_set_planemask(pixmap, ~0); + return; -fail: - glamor_set_planemask(pixmap, ~0); - glamor_fallback("to %p (%c)\n", - drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { - fbPutImage(&pixmap->drawable, gc, depth, x, y, w, h, left_pad, image_format, - bits); - glamor_finish_access(&pixmap->drawable); - } + fail: + glamor_set_planemask(pixmap, ~0); + glamor_fallback("to %p (%c)\n", + drawable, glamor_get_drawable_location(drawable)); + if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { + fbPutImage(&pixmap->drawable, gc, depth, x, y, w, h, + left_pad, image_format, bits); + glamor_finish_access(&pixmap->drawable); + } } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index d649c9813..7f52c7b34 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -39,446 +39,452 @@ //#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(glamor_gl_dispatch *dispatch, struct shader_key *key) +glamor_create_composite_fs(glamor_gl_dispatch * dispatch, + struct shader_key *key) { - const char *source_solid_fetch = - GLAMOR_DEFAULT_PRECISION - "uniform vec4 source;\n" - "vec4 get_source()\n" - "{\n" - " return source;\n" - "}\n"; - const char *source_alpha_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION - "varying vec2 source_texture;\n" - "uniform sampler2D source_sampler;\n" - "vec4 get_source()\n" - "{\n" - " return texture2D(source_sampler, source_texture);\n" - "}\n"; - const char *source_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION - "varying vec2 source_texture;\n" - "uniform sampler2D source_sampler;\n" - "vec4 get_source()\n" - "{\n" - " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" - "}\n"; - const char *mask_solid_fetch = - GLAMOR_DEFAULT_PRECISION - "uniform vec4 mask;\n" - "vec4 get_mask()\n" - "{\n" - " return mask;\n" - "}\n"; - const char *mask_alpha_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION - "varying vec2 mask_texture;\n" - "uniform sampler2D mask_sampler;\n" - "vec4 get_mask()\n" - "{\n" - " return texture2D(mask_sampler, mask_texture);\n" - "}\n"; - const char *mask_pixmap_fetch = - GLAMOR_DEFAULT_PRECISION - "varying vec2 mask_texture;\n" - "uniform sampler2D mask_sampler;\n" - "vec4 get_mask()\n" - "{\n" - " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" - "}\n"; - const char *in_source_only = - GLAMOR_DEFAULT_PRECISION - "void main()\n" - "{\n" - " gl_FragColor = get_source();\n" - "}\n"; - const char *in_normal = - GLAMOR_DEFAULT_PRECISION - "void main()\n" - "{\n" - " gl_FragColor = get_source() * get_mask().a;\n" - "}\n"; - const char *in_ca_source = - GLAMOR_DEFAULT_PRECISION - "void main()\n" - "{\n" - " gl_FragColor = get_source() * get_mask();\n" - "}\n"; - const char *in_ca_alpha = - GLAMOR_DEFAULT_PRECISION - "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 = + GLAMOR_DEFAULT_PRECISION + "uniform vec4 source;\n" + "vec4 get_source()\n" "{\n" " return source;\n" "}\n"; + const char *source_alpha_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION + "varying vec2 source_texture;\n" + "uniform sampler2D source_sampler;\n" + "vec4 get_source()\n" + "{\n" " return texture2D(source_sampler, source_texture);\n" + "}\n"; + const char *source_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" + "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" + "{\n" + " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" + "}\n"; + const char *mask_solid_fetch = + GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" + "vec4 get_mask()\n" "{\n" " return mask;\n" "}\n"; + const char *mask_alpha_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" + "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" + " return texture2D(mask_sampler, mask_texture);\n" "}\n"; + const char *mask_pixmap_fetch = + GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" + "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" + " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" + "}\n"; + const char *in_source_only = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" + " gl_FragColor = get_source();\n" "}\n"; + const char *in_normal = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" + " gl_FragColor = get_source() * get_mask().a;\n" "}\n"; + const char *in_ca_source = + GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" + " gl_FragColor = get_source() * get_mask();\n" "}\n"; + const char *in_ca_alpha = + GLAMOR_DEFAULT_PRECISION "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(dispatch, GL_FRAGMENT_SHADER, source); - free(source); - return prog; + prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + source); + free(source); + + return prog; } static GLuint -glamor_create_composite_vs(glamor_gl_dispatch *dispatch, struct shader_key *key) +glamor_create_composite_vs(glamor_gl_dispatch * dispatch, + struct shader_key *key) { - const char *main_opening = - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord0;\n" - "attribute vec4 v_texcoord1;\n" - "varying vec2 source_texture;\n" - "varying vec2 mask_texture;\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n"; - const char *source_coords = - " source_texture = v_texcoord0.xy;\n"; - const char *mask_coords = - " mask_texture = v_texcoord1.xy;\n"; - const char *main_closing = - "}\n"; - const char *source_coords_setup = ""; - const char *mask_coords_setup = ""; - char *source; - GLuint prog; + const char *main_opening = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "attribute vec4 v_texcoord1;\n" + "varying vec2 source_texture;\n" + "varying vec2 mask_texture;\n" + "void main()\n" "{\n" " gl_Position = v_position;\n"; + const char *source_coords = + " source_texture = v_texcoord0.xy;\n"; + const char *mask_coords = " mask_texture = v_texcoord1.xy;\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(dispatch, GL_VERTEX_SHADER, source); - free(source); + prog = + glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, source); + free(source); - return prog; + return prog; } static void glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, - glamor_composite_shader *shader) + glamor_composite_shader * shader) { - GLuint vs, fs, prog; - GLint source_sampler_uniform_location, mask_sampler_uniform_location; - glamor_screen_private *glamor = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor->dispatch; + GLuint vs, fs, prog; + GLint source_sampler_uniform_location, + mask_sampler_uniform_location; + glamor_screen_private *glamor = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor->dispatch; - vs = glamor_create_composite_vs(dispatch, key); - if (vs == 0) - return; - fs = glamor_create_composite_fs(dispatch, key); - if (fs == 0) - return; + vs = glamor_create_composite_vs(dispatch, key); + if (vs == 0) + return; + fs = glamor_create_composite_fs(dispatch, key); + if (fs == 0) + return; - prog = dispatch->glCreateProgram(); - dispatch->glAttachShader(prog, vs); - dispatch->glAttachShader(prog, fs); + prog = dispatch->glCreateProgram(); + dispatch->glAttachShader(prog, vs); + dispatch->glAttachShader(prog, fs); - dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position"); - dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_POS, + "v_position"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, + "v_texcoord0"); + dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, + "v_texcoord1"); - glamor_link_glsl_prog(dispatch, prog); + glamor_link_glsl_prog(dispatch, prog); - shader->prog = prog; + shader->prog = prog; - dispatch->glUseProgram(prog); + dispatch->glUseProgram(prog); - if (key->source == SHADER_SOURCE_SOLID) { - shader->source_uniform_location = dispatch->glGetUniformLocation(prog, - "source"); - } else { - source_sampler_uniform_location = dispatch->glGetUniformLocation(prog, - "source_sampler"); - dispatch->glUniform1i(source_sampler_uniform_location, 0); - } + if (key->source == SHADER_SOURCE_SOLID) { + shader->source_uniform_location = + dispatch->glGetUniformLocation(prog, "source"); + } else { + source_sampler_uniform_location = + dispatch->glGetUniformLocation(prog, "source_sampler"); + dispatch->glUniform1i(source_sampler_uniform_location, 0); + } - if (key->mask != SHADER_MASK_NONE) { - if (key->mask == SHADER_MASK_SOLID) { - shader->mask_uniform_location = dispatch->glGetUniformLocation(prog, - "mask"); - } else { - mask_sampler_uniform_location = dispatch->glGetUniformLocation(prog, - "mask_sampler"); - dispatch->glUniform1i(mask_sampler_uniform_location, 1); - } - } + if (key->mask != SHADER_MASK_NONE) { + if (key->mask == SHADER_MASK_SOLID) { + shader->mask_uniform_location = + dispatch->glGetUniformLocation(prog, "mask"); + } else { + mask_sampler_uniform_location = + dispatch->glGetUniformLocation(prog, + "mask_sampler"); + dispatch->glUniform1i + (mask_sampler_uniform_location, 1); + } + } } static glamor_composite_shader * -glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) +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; } + #define GLAMOR_COMPOSITE_VBO_SIZE 8192 static void glamor_reset_composite_vbo(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_priv->vbo_offset = 0; - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_SIZE; - glamor_priv->render_nr_verts = 0; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_priv->vbo_offset = 0; + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_SIZE; + glamor_priv->render_nr_verts = 0; } void glamor_init_composite_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_priv->vb = malloc(GLAMOR_COMPOSITE_VBO_SIZE); - assert(glamor_priv->vb != NULL); - glamor_reset_composite_vbo(screen); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_priv->vb = malloc(GLAMOR_COMPOSITE_VBO_SIZE); + assert(glamor_priv->vb != NULL); + glamor_reset_composite_vbo(screen); } static Bool glamor_set_composite_op(ScreenPtr screen, CARD8 op, PicturePtr dest, PicturePtr mask) { - GLenum source_blend, dest_blend; - struct blendinfo *op_info; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + GLenum source_blend, dest_blend; + struct blendinfo *op_info; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (op >= ARRAY_SIZE(composite_op_info)) { - glamor_fallback("unsupported render op %d \n", op); - return GL_FALSE; - } - op_info = &composite_op_info[op]; + 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; + 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; - } + /* 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; - } - 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; - } + /* 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; + } + 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) { - dispatch->glDisable(GL_BLEND); - } else { - dispatch->glEnable(GL_BLEND); - dispatch->glBlendFunc(source_blend, dest_blend); - } - return TRUE; + if (source_blend == GL_ONE && dest_blend == GL_ZERO) { + dispatch->glDisable(GL_BLEND); + } else { + dispatch->glEnable(GL_BLEND); + dispatch->glBlendFunc(source_blend, dest_blend); + } + return TRUE; } static void -glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, - glamor_pixmap_private *pixmap_priv) +glamor_set_composite_texture(ScreenPtr screen, int unit, + PicturePtr picture, + glamor_pixmap_private * pixmap_priv) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - dispatch->glActiveTexture(GL_TEXTURE0 + unit); - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - switch (picture->repeatType) { - case RepeatNone: + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + dispatch->glActiveTexture(GL_TEXTURE0 + unit); + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + switch (picture->repeatType) { + case RepeatNone: #ifndef GLAMOR_GLES2 - /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */ - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + /* XXX GLES2 doesn't support GL_CLAMP_TO_BORDER. */ + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_BORDER); #endif - break; - case RepeatNormal: - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - break; - case RepeatPad: - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - break; - case RepeatReflect: - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - break; - } + break; + case RepeatNormal: + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_REPEAT); + break; + case RepeatPad: + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + break; + case RepeatReflect: + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_MIRRORED_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_MIRRORED_REPEAT); + break; + } - switch (picture->filter) { - case PictFilterNearest: - dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case PictFilterBilinear: - default: - dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - dispatch->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - } + switch (picture->filter) { + case PictFilterNearest: + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + break; + case PictFilterBilinear: + default: + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + break; + } #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif } static void -glamor_set_composite_solid(glamor_gl_dispatch *dispatch, float *color, GLint uniform_location) +glamor_set_composite_solid(glamor_gl_dispatch * dispatch, float *color, + GLint uniform_location) { - dispatch->glUniform4fv(uniform_location, 1, color); + dispatch->glUniform4fv(uniform_location, 1, color); } static int -compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) +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 '?'; - } - } - return glamor_get_drawable_location(picture->pDrawable); + 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); } static Bool @@ -488,119 +494,127 @@ glamor_composite_with_copy(CARD8 op, INT16 x_source, INT16 y_source, INT16 x_dest, - INT16 y_dest, - CARD16 width, - CARD16 height) + INT16 y_dest, 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; + 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; + 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 void glamor_setup_composite_vbo(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - 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); - dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - glamor_priv->vb_stride, - (void *)((long)glamor_priv->vbo_offset)); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long) + glamor_priv->vbo_offset)); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - if (glamor_priv->has_source_coords) { - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - glamor_priv->vb_stride, - (void *)((long)glamor_priv->vbo_offset + 2 * sizeof(float))); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - } + if (glamor_priv->has_source_coords) { + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, + (void *) ((long) + glamor_priv->vbo_offset + + + 2 * + sizeof(float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + } - if (glamor_priv->has_mask_coords) { - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE, - glamor_priv->vb_stride, - (void *)((long)glamor_priv->vbo_offset + - (glamor_priv->has_source_coords ? 4 : 2) * - sizeof(float))); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); - } + if (glamor_priv->has_mask_coords) { + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, + GL_FLOAT, GL_FALSE, + glamor_priv->vb_stride, + (void *) ((long) + glamor_priv->vbo_offset + + + (glamor_priv->has_source_coords + ? 4 : 2) * + sizeof(float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); + } } static void glamor_emit_composite_vert(ScreenPtr screen, const float *src_coords, const float *mask_coords, - const float *dst_coords, - int i) + 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_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (!glamor_priv->render_nr_verts) - return; - dispatch->glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, glamor_priv->vb, - GL_STREAM_DRAW); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + if (!glamor_priv->render_nr_verts) + return; + dispatch->glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, + glamor_priv->vb, GL_STREAM_DRAW); - dispatch->glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts); - glamor_reset_composite_vbo(screen); + dispatch->glDrawArrays(GL_TRIANGLES, 0, + glamor_priv->render_nr_verts); + glamor_reset_composite_vbo(screen); } static void @@ -609,93 +623,100 @@ 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_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (glamor_priv->vbo_offset + 6 * glamor_priv->vb_stride > - glamor_priv->vbo_size) - { - glamor_flush_composite_rects(screen); - } + if (glamor_priv->vbo_offset + 6 * glamor_priv->vb_stride > + glamor_priv->vbo_size) { + glamor_flush_composite_rects(screen); + } - if (glamor_priv->vbo_offset == 0) { - if (glamor_priv->vbo == 0) - dispatch->glGenBuffers(1, &glamor_priv->vbo); + if (glamor_priv->vbo_offset == 0) { + if (glamor_priv->vbo == 0) + dispatch->glGenBuffers(1, &glamor_priv->vbo); - glamor_setup_composite_vbo(screen); - } + 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, 0); - 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, 0); + 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}, - }; +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) +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); + 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); + assert(src_bpp == mask_bpp); - 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; - } + 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; - } + 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; + 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 @@ -703,425 +724,470 @@ glamor_composite_with_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - int nrect, - glamor_composite_rect_t *rects) + int nrect, glamor_composite_rect_t * rects) { - ScreenPtr screen = dest->pDrawable->pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - 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; - GLfloat dst_xscale, dst_yscale; - GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; - 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; - float src_matrix[9], mask_matrix[9]; - GLfloat source_solid_color[4], mask_solid_color[4]; + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + 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; + GLfloat dst_xscale, dst_yscale; + GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = + 1, src_yscale = 1; + 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; + float src_matrix[9], mask_matrix[9]; + GLfloat source_solid_color[4], mask_solid_color[4]; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - 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; - glamor_get_rgba_from_pixel(source->pSourcePict->solidFill.color, - &source_solid_color[0], - &source_solid_color[1], - &source_solid_color[2], - &source_solid_color[3], - PICT_a8r8g8b8); - } else { - glamor_fallback("gradient source\n"); - goto fail; - } - } else { - key.source = SHADER_SOURCE_TEXTURE_ALPHA; - } - if (mask) { - if (!mask->pDrawable) { - if (mask->pSourcePict->type == SourcePictTypeSolidFill) { - key.mask = SHADER_MASK_SOLID; - glamor_get_rgba_from_pixel(mask->pSourcePict->solidFill.color, - &mask_solid_color[0], - &mask_solid_color[1], - &mask_solid_color[2], - &mask_solid_color[3], - PICT_a8r8g8b8); - } else { - glamor_fallback("gradient mask\n"); - goto fail; - } - } else { - key.mask = SHADER_MASK_TEXTURE_ALPHA; - } + 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; + glamor_get_rgba_from_pixel(source-> + pSourcePict->solidFill. + color, + &source_solid_color[0], + &source_solid_color[1], + &source_solid_color[2], + &source_solid_color[3], + PICT_a8r8g8b8); + } else { + glamor_fallback("gradient source\n"); + goto fail; + } + } else { + key.source = SHADER_SOURCE_TEXTURE_ALPHA; + } + if (mask) { + if (!mask->pDrawable) { + if (mask->pSourcePict->type == + SourcePictTypeSolidFill) { + key.mask = SHADER_MASK_SOLID; + glamor_get_rgba_from_pixel + (mask->pSourcePict->solidFill.color, + &mask_solid_color[0], + &mask_solid_color[1], + &mask_solid_color[2], + &mask_solid_color[3], PICT_a8r8g8b8); + } else { + glamor_fallback("gradient mask\n"); + goto fail; + } + } else { + key.mask = SHADER_MASK_TEXTURE_ALPHA; + } - 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.mask = SHADER_MASK_NONE; - key.in = SHADER_IN_SOURCE_ONLY; - } + 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.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_fbo == 0) { - /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex - * equal to zero when the pixmap is screen pixmap. Then we may - * refer the tex zero directly latter in the composition. - * It seems that it works fine, but it may have potential problem*/ + 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_fbo == 0) { + /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex + * equal to zero when the pixmap is screen pixmap. Then we may + * refer the tex zero directly latter in the composition. + * It seems that it works fine, but it may have potential problem*/ #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - source_status = GLAMOR_UPLOAD_PENDING; + source_status = GLAMOR_UPLOAD_PENDING; #else - glamor_fallback("no texture in source\n"); - goto fail; + glamor_fallback("no texture in source\n"); + goto fail; #endif - } - else if (source_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) { - key.source = SHADER_SOURCE_SOLID; - memcpy(source_solid_color, source_pixmap_priv->pending_op.fill.color4fv, 4 * sizeof(float)); - } - } - 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_fbo == 0) { + } else if (source_pixmap_priv->pending_op.type == + GLAMOR_PENDING_FILL) { + key.source = SHADER_SOURCE_SOLID; + memcpy(source_solid_color, + source_pixmap_priv->pending_op. + fill.color4fv, 4 * sizeof(float)); + } + } + 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_fbo == 0) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - mask_status = GLAMOR_UPLOAD_PENDING; + mask_status = GLAMOR_UPLOAD_PENDING; #else - glamor_fallback("no texture in mask\n"); - goto fail; + glamor_fallback("no texture in mask\n"); + goto fail; #endif - } - else if (mask_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) { - key.mask = SHADER_MASK_SOLID; - memcpy(mask_solid_color, mask_pixmap_priv->pending_op.fill.color4fv, 4 * sizeof(float)); - } - } + } else if (mask_pixmap_priv->pending_op.type == + GLAMOR_PENDING_FILL) { + key.mask = SHADER_MASK_SOLID; + memcpy(mask_solid_color, + mask_pixmap_priv->pending_op.fill.color4fv, + 4 * sizeof(float)); + } + } #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - if (source_status == GLAMOR_UPLOAD_PENDING - && mask_status == GLAMOR_UPLOAD_PENDING - && source_pixmap == mask_pixmap) { + 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; + if (source->format != mask->format) { + saved_source_format = source->format; - 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 (!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; + 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; - 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 (!PICT_FORMAT_A(mask->format) + && PICT_FORMAT_A(saved_source_format)) + key.mask = SHADER_MASK_TEXTURE; - 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; - } - } + mask_status = GLAMOR_NONE; + } + source_status = glamor_upload_picture_to_texture(source); - 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 (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; + } + } + + 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; + } + } + } #endif - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - glamor_validate_pixmap(dest_pixmap); - if (!glamor_set_composite_op(screen, op, dest, mask)) { - goto fail; - } + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + glamor_validate_pixmap(dest_pixmap); + if (!glamor_set_composite_op(screen, op, dest, mask)) { + goto fail; + } - shader = glamor_lookup_composite_shader(screen, &key); - if (shader->prog == 0) { - glamor_fallback("no shader program for this render acccel mode\n"); - goto fail; - } + shader = glamor_lookup_composite_shader(screen, &key); + if (shader->prog == 0) { + glamor_fallback + ("no shader program for this render acccel mode\n"); + goto fail; + } - dispatch->glUseProgram(shader->prog); + dispatch->glUseProgram(shader->prog); - if (key.source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(dispatch, source_solid_color, 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(dispatch, mask_solid_color, shader->mask_uniform_location); - } else { - glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); - } - } + if (key.source == SHADER_SOURCE_SOLID) { + glamor_set_composite_solid(dispatch, source_solid_color, + 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(dispatch, + mask_solid_color, + 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_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); - pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, + &dest_x_off, &dest_y_off); + pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); - if (glamor_priv->has_source_coords) { - glamor_get_drawable_deltas(source->pDrawable, source_pixmap, - &source_x_off, &source_y_off); - pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); - glamor_picture_get_matrixf(source, src_matrix); - } + if (glamor_priv->has_source_coords) { + glamor_get_drawable_deltas(source->pDrawable, + source_pixmap, &source_x_off, + &source_y_off); + pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, + &src_yscale); + glamor_picture_get_matrixf(source, src_matrix); + } - if (glamor_priv->has_mask_coords) { - glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, - &mask_x_off, &mask_y_off); - pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); - glamor_picture_get_matrixf(mask, mask_matrix); - } + if (glamor_priv->has_mask_coords) { + glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, + &mask_x_off, &mask_y_off); + pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, + &mask_yscale); + glamor_picture_get_matrixf(mask, mask_matrix); + } - while (nrect--) { - INT16 x_source; - INT16 y_source; - INT16 x_mask; - INT16 y_mask; - INT16 x_dest; - INT16 y_dest; - CARD16 width; - CARD16 height; + 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 = 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; - } + 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; + 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++) { - int vx1 = box[i].x1 + dest_x_off; - int vx2 = box[i].x2 + dest_x_off; - int vy1 = box[i].y1 + dest_y_off; - int vy2 = box[i].y2 + dest_y_off; - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, vx1, vy1, vx2, vy2, - glamor_priv->yInverted, vertices); + x_source += source_x_off; + y_source += source_y_off; + x_mask += mask_x_off; + y_mask += mask_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; - if (source->transform) - glamor_set_transformed_normalize_tcoords(src_matrix, src_xscale, src_yscale, - tx1, ty1, tx2, ty2, - glamor_priv->yInverted, - source_texcoords); - else - glamor_set_normalize_tcoords(src_xscale, src_yscale, tx1, ty1, tx2, ty2, - glamor_priv->yInverted, source_texcoords); - } + box = REGION_RECTS(®ion); + for (i = 0; i < REGION_NUM_RECTS(®ion); i++) { + int vx1 = box[i].x1 + dest_x_off; + int vx2 = box[i].x2 + dest_x_off; + int vy1 = box[i].y1 + dest_y_off; + int vy2 = box[i].y2 + dest_y_off; + glamor_set_normalize_vcoords(dst_xscale, + dst_yscale, vx1, + vy1, vx2, vy2, + glamor_priv->yInverted, + vertices); - 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; - if (mask->transform) - glamor_set_transformed_normalize_tcoords(mask_matrix, mask_xscale, mask_yscale, - tx1, ty1, tx2, ty2, - glamor_priv->yInverted, - mask_texcoords); - else - glamor_set_normalize_tcoords(mask_xscale, mask_yscale, tx1, ty1, tx2, ty2, - glamor_priv->yInverted, mask_texcoords); - } - glamor_emit_composite_rect(screen, source_texcoords, - mask_texcoords, vertices); - } - rects++; - } - glamor_flush_composite_rects(screen); + 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; + if (source->transform) + glamor_set_transformed_normalize_tcoords + (src_matrix, src_xscale, + src_yscale, tx1, ty1, + tx2, ty2, + glamor_priv->yInverted, + source_texcoords); + else + glamor_set_normalize_tcoords + (src_xscale, src_yscale, + tx1, ty1, tx2, ty2, + glamor_priv->yInverted, + source_texcoords); + } - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); - REGION_UNINIT(dst->pDrawable->pScreen, ®ion); - dispatch->glDisable(GL_BLEND); + 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; + if (mask->transform) + glamor_set_transformed_normalize_tcoords + (mask_matrix, + mask_xscale, + mask_yscale, tx1, ty1, + tx2, ty2, + glamor_priv->yInverted, + mask_texcoords); + else + glamor_set_normalize_tcoords + (mask_xscale, + mask_yscale, tx1, ty1, + tx2, ty2, + glamor_priv->yInverted, + mask_texcoords); + } + glamor_emit_composite_rect(screen, + source_texcoords, + mask_texcoords, + vertices); + } + rects++; + } + glamor_flush_composite_rects(screen); + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); + REGION_UNINIT(dst->pDrawable->pScreen, ®ion); + dispatch->glDisable(GL_BLEND); #ifndef GLAMOR_GLES2 - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glDisable(GL_TEXTURE_2D); - dispatch->glActiveTexture(GL_TEXTURE1); - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE1); + dispatch->glDisable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(0); - if (saved_source_format) - source->format = saved_source_format; - return TRUE; + dispatch->glUseProgram(0); + if (saved_source_format) + source->format = saved_source_format; + return TRUE; - fail: - if (saved_source_format) - source->format = saved_source_format; + fail: + if (saved_source_format) + source->format = saved_source_format; - dispatch->glDisable(GL_BLEND); - dispatch->glUseProgram(0); - return FALSE; + dispatch->glDisable(GL_BLEND); + dispatch->glUseProgram(0); + return FALSE; } static PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, - PicturePtr source, - int x_source, - int y_source, - int width, - int height) + PicturePtr source, + int x_source, + int y_source, int width, int height) { - PixmapPtr pixmap; - PicturePtr dst; - int error; - PictFormatShort format; + PixmapPtr pixmap; + PicturePtr dst; + int error; + PictFormatShort format; - if (!source->pDrawable) - format = PICT_a8r8g8b8; - else - format = source->format; + if (!source->pDrawable) + format = PICT_a8r8g8b8; + else + format = source->format; - pixmap = screen->CreatePixmap(screen, - width, - height, - PIXMAN_FORMAT_DEPTH(format), - GLAMOR_CREATE_PIXMAP_CPU); + pixmap = screen->CreatePixmap(screen, + width, + height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_CPU); - if (!pixmap) - return NULL; - - dst = CreatePicture(0, - &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), - format), - 0, - 0, - serverClient, - &error); - screen->DestroyPixmap(pixmap); - if (!dst) - return NULL; + if (!pixmap) + return NULL; - ValidatePicture(dst); + dst = CreatePicture(0, + &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + if (!dst) + return NULL; - fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, - 0, 0, 0, 0, width, height); - return dst; + ValidatePicture(dst); + + fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, + 0, 0, 0, 0, width, height); + return dst; } void @@ -1133,166 +1199,182 @@ glamor_composite(CARD8 op, INT16 y_source, INT16 x_mask, INT16 y_mask, - INT16 x_dest, - INT16 y_dest, - CARD16 width, - CARD16 height) + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { - ScreenPtr screen = dest->pDrawable->pScreen; - glamor_pixmap_private *dest_pixmap_priv; - glamor_pixmap_private *source_pixmap_priv = NULL, *mask_pixmap_priv = NULL; - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); - PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; - PicturePtr temp_src = source, temp_mask = mask; - int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; - glamor_composite_rect_t rect; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_pixmap_private *dest_pixmap_priv; + glamor_pixmap_private *source_pixmap_priv = + NULL, *mask_pixmap_priv = NULL; + PixmapPtr dest_pixmap = + glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; + PicturePtr temp_src = source, temp_mask = mask; + int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; + glamor_composite_rect_t rect; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - x_temp_src = x_source; - y_temp_src = y_source; - x_temp_mask = x_mask; - y_temp_mask = y_mask; + x_temp_src = x_source; + y_temp_src = y_source; + x_temp_mask = x_mask; + y_temp_mask = y_mask; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - /* Currently. Always fallback to cpu if destination is in CPU memory. */ - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - goto fail; - } + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + /* Currently. Always fallback to cpu if destination is in CPU memory. */ + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + goto fail; + } - if (source->pDrawable) { - source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - } + if (source->pDrawable) { + source_pixmap = + glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = + glamor_get_pixmap_private(source_pixmap); + } - if (mask && mask->pDrawable) { - mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - } + if (mask && mask->pDrawable) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + } - if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) - || (source->pDrawable - && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) - && ((width * height * 4 - < (source_pixmap->drawable.width * source_pixmap->drawable.height)) - || !(glamor_check_fbo_size(glamor_priv, source_pixmap->drawable.width, - source_pixmap->drawable.height))))) { - temp_src = glamor_convert_gradient_picture(screen, source, x_source, y_source, width, height); - if (!temp_src) { - temp_src = source; - goto fail; - } - x_temp_src = y_temp_src = 0; - } + if ((!source->pDrawable + && (source->pSourcePict->type != SourcePictTypeSolidFill)) + || (source->pDrawable + && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) + && + ((width * height * 4 < + (source_pixmap->drawable.width * + source_pixmap->drawable.height)) + || + !(glamor_check_fbo_size + (glamor_priv, source_pixmap->drawable.width, + source_pixmap->drawable.height))))) { + temp_src = + glamor_convert_gradient_picture(screen, source, + x_source, y_source, + width, height); + if (!temp_src) { + temp_src = source; + goto fail; + } + x_temp_src = y_temp_src = 0; + } - if (mask - && ((!mask->pDrawable && (mask->pSourcePict->type != SourcePictTypeSolidFill)) - || (mask->pDrawable - && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) - && ((width * height * 4 - < (mask_pixmap->drawable.width * mask_pixmap->drawable.height)) - || !(glamor_check_fbo_size(glamor_priv, mask_pixmap->drawable.width, - mask_pixmap->drawable.height)))))) { - /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity - * to do reduce one convertion. */ - temp_mask = glamor_convert_gradient_picture(screen, mask, x_mask, y_mask, width, height); - if (!temp_mask) { - temp_mask = mask; - goto fail; - } - x_temp_mask = y_temp_mask = 0; - } - /* Do two-pass PictOpOver componentAlpha, until we enable - * dual source color blending. - */ + if (mask + && + ((!mask->pDrawable + && (mask->pSourcePict->type != SourcePictTypeSolidFill)) + || (mask->pDrawable + && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) + && + ((width * height * 4 < + (mask_pixmap->drawable.width * + mask_pixmap->drawable.height)) + || + !(glamor_check_fbo_size + (glamor_priv, mask_pixmap->drawable.width, + mask_pixmap->drawable.height)))))) { + /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity + * to do reduce one convertion. */ + temp_mask = + glamor_convert_gradient_picture(screen, mask, + x_mask, y_mask, + width, height); + if (!temp_mask) { + temp_mask = mask; + goto fail; + } + x_temp_mask = y_temp_mask = 0; + } + /* Do two-pass PictOpOver componentAlpha, until we enable + * dual source color blending. + */ - if (mask && mask->componentAlpha) { - if (op == PictOpOver) { - glamor_composite(PictOpOutReverse, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, - width, height); - glamor_composite(PictOpAdd, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, - width, height); - goto done; + if (mask && mask->componentAlpha) { + if (op == PictOpOver) { + glamor_composite(PictOpOutReverse, + temp_src, temp_mask, dest, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, + x_dest, y_dest, width, height); + glamor_composite(PictOpAdd, + temp_src, temp_mask, dest, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, + x_dest, y_dest, width, height); + goto done; - } else if (op != PictOpAdd && op != PictOpOutReverse) { - glamor_fallback("glamor_composite(): component alpha\n"); - goto fail; - } - } + } else if (op != PictOpAdd && op != PictOpOutReverse) { + glamor_fallback + ("glamor_composite(): component alpha\n"); + goto fail; + } + } - if (!mask) { - if (glamor_composite_with_copy(op, temp_src, dest, - x_temp_src, y_temp_src, - x_dest, y_dest, - width, height)) - goto done; - } + if (!mask) { + if (glamor_composite_with_copy(op, temp_src, dest, + x_temp_src, y_temp_src, + x_dest, y_dest, width, + height)) + goto done; + } - rect.x_src = x_temp_src; - rect.y_src = y_temp_src; - rect.x_mask = x_temp_mask; - rect.y_mask = y_temp_mask; - rect.x_dst = x_dest; - rect.y_dst = y_dest; - rect.width = width; - rect.height = height; - if (glamor_composite_with_shader(op, temp_src, temp_mask, dest, 1, &rect)) - goto done; + rect.x_src = x_temp_src; + rect.y_src = y_temp_src; + rect.x_mask = x_temp_mask; + rect.y_mask = y_temp_mask; + rect.x_dst = x_dest; + rect.y_dst = y_dest; + rect.width = width; + rect.height = height; + if (glamor_composite_with_shader + (op, temp_src, temp_mask, dest, 1, &rect)) + goto done; -fail: + fail: - glamor_fallback( - "from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", - source, - source->pDrawable, - source->pDrawable ? source->pDrawable->width : 0, - source->pDrawable ? source->pDrawable->height : 0, - mask, - (!mask) ? NULL : mask->pDrawable, - (!mask || !mask->pDrawable)? 0 : mask->pDrawable->width, - (!mask || !mask->pDrawable)? 0 : mask->pDrawable->height, - glamor_get_picture_location(source), - glamor_get_picture_location(mask), - dest, - dest->pDrawable, - dest->pDrawable->width, - dest->pDrawable->height, - glamor_get_picture_location(dest)); + glamor_fallback + ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", + source, source->pDrawable, + source->pDrawable ? source->pDrawable->width : 0, + source->pDrawable ? source->pDrawable->height : 0, mask, + (!mask) ? NULL : mask->pDrawable, (!mask + || !mask->pDrawable) ? 0 : + mask->pDrawable->width, (!mask + || !mask-> + pDrawable) ? 0 : mask->pDrawable-> + height, glamor_get_picture_location(source), + glamor_get_picture_location(mask), dest, dest->pDrawable, + dest->pDrawable->width, dest->pDrawable->height, + glamor_get_picture_location(dest)); - dispatch->glUseProgram(0); - dispatch->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); - } -done: - if (temp_src != source) - FreePicture(temp_src, 0); - if (temp_mask != mask) - FreePicture(temp_mask, 0); + dispatch->glUseProgram(0); + dispatch->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); + } + done: + if (temp_src != source) + FreePicture(temp_src, 0); + if (temp_mask != mask) + FreePicture(temp_mask, 0); } @@ -1304,31 +1386,32 @@ static PicturePtr glamor_create_mask_picture(ScreenPtr screen, PicturePtr dst, PictFormatPtr pict_format, - CARD16 width, - CARD16 height) + 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, 0, 0, - pict_format->depth, - GLAMOR_CREATE_PIXMAP_CPU); - if (!pixmap) - return 0; - picture = CreatePicture(0, &pixmap->drawable, pict_format, - 0, 0, serverClient, &error); - screen->DestroyPixmap(pixmap); - return picture; + pixmap = screen->CreatePixmap(screen, 0, 0, + pict_format->depth, + GLAMOR_CREATE_PIXMAP_CPU); + if (!pixmap) + return 0; + picture = CreatePicture(0, &pixmap->drawable, pict_format, + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + return picture; } /** @@ -1339,108 +1422,110 @@ void glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid *traps) + 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; - pixman_image_t *image; + 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; + 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; - } + /* 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); + miTrapezoidBounds(ntrap, traps, &bounds); - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; + 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; + 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 = PixmapBytePad(width, mask_format->depth); - picture = glamor_create_mask_picture(screen, dst, mask_format, - width, height); - if (!picture) - return; + width = bounds.x2 - bounds.x1; + height = bounds.y2 - bounds.y1; + stride = PixmapBytePad(width, mask_format->depth); + 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; - } + 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); + for (; ntrap; ntrap--, traps++) + pixman_rasterize_trapezoid(image, + (pixman_trapezoid_t *) traps, + -bounds.x1, -bounds.y1); - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - - screen->ModifyPixmapHeader(pixmap, width, height, - mask_format->depth, - BitsPerPixel(mask_format->depth), - PixmapBytePad(width, mask_format->depth), - pixman_image_get_data(image)); + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - 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); + screen->ModifyPixmapHeader(pixmap, width, height, + mask_format->depth, + BitsPerPixel(mask_format->depth), + PixmapBytePad(width, + mask_format->depth), + pixman_image_get_data(image)); - 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); + pixman_image_unref(image); + + FreePicture(picture, 0); } void glamor_composite_rects(CARD8 op, PicturePtr src, PicturePtr mask, PicturePtr dst, - int nrect, glamor_composite_rect_t *rects) + 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, mask, dst, nrect, rects)) - return; + if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) + return; - n = nrect; - r = rects; + n = nrect; + r = rects; - while (n--) { - CompositePicture(op, - src, - mask, - dst, - r->x_src, r->y_src, - r->x_mask, r->y_mask, - r->x_dst, r->y_dst, - r->width, r->height); - r++; - } + while (n--) { + CompositePicture(op, + src, + mask, + dst, + r->x_src, r->y_src, + r->x_mask, r->y_mask, + r->x_dst, r->y_dst, r->width, r->height); + r++; + } } -#endif /* RENDER */ +#endif /* RENDER */ diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index bb4bffdd9..61163ce9b 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -35,76 +35,72 @@ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted) { - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - GLenum format, type; - int no_alpha, no_revert, i; - uint8_t *drawpixels_src = (uint8_t *)src; - RegionPtr clip = fbGetCompositeClip(gc); - BoxRec *pbox; - int x_off, y_off; + PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + glamor_screen_private *glamor_priv = + glamor_get_screen_private(drawable->pScreen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + GLenum format, type; + int no_alpha, no_revert, i; + uint8_t *drawpixels_src = (uint8_t *) src; + RegionPtr clip = fbGetCompositeClip(gc); + BoxRec *pbox; + int x_off, y_off; - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - glamor_fallback("ES2 fallback.\n"); - goto fail; - } - - if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, - &format, - &type, - &no_alpha, - &no_revert - )) { - glamor_fallback("unknown depth. %d \n", - drawable->depth); - goto fail; - } - - - if (glamor_set_destination_pixmap(dest_pixmap)) - goto fail; - - glamor_validate_pixmap(dest_pixmap); - if (!glamor_set_planemask(dest_pixmap, gc->planemask)) - goto fail; - glamor_set_alu(dispatch, gc->alu); - if (!glamor_set_planemask(dest_pixmap, gc->planemask)) - goto fail; - - glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); - - for (i = 0; i < n; i++) { - - n = REGION_NUM_RECTS(clip); - pbox = REGION_RECTS(clip); - while (n--) { - if (pbox->y1 > points[i].y) - break; - dispatch->glScissor(pbox->x1, - points[i].y + y_off, - pbox->x2 - pbox->x1, - 1); - dispatch->glEnable(GL_SCISSOR_TEST); - dispatch->glRasterPos2i(points[i].x + x_off, - points[i].y + y_off); - dispatch->glDrawPixels(widths[i], - 1, - format, type, - drawpixels_src); + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + glamor_fallback("ES2 fallback.\n"); + goto fail; } - drawpixels_src += PixmapBytePad(widths[i], drawable->depth); - } - glamor_set_planemask(dest_pixmap, ~0); - glamor_set_alu(dispatch, GXcopy); - dispatch->glDisable(GL_SCISSOR_TEST); - return; -fail: - 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); - glamor_finish_access(drawable); - } + if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, + &format, + &type, &no_alpha, + &no_revert)) { + glamor_fallback("unknown depth. %d \n", drawable->depth); + goto fail; + } + + + if (glamor_set_destination_pixmap(dest_pixmap)) + goto fail; + + glamor_validate_pixmap(dest_pixmap); + if (!glamor_set_planemask(dest_pixmap, gc->planemask)) + goto fail; + glamor_set_alu(dispatch, gc->alu); + if (!glamor_set_planemask(dest_pixmap, gc->planemask)) + goto fail; + + glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); + + for (i = 0; i < n; i++) { + + n = REGION_NUM_RECTS(clip); + pbox = REGION_RECTS(clip); + while (n--) { + if (pbox->y1 > points[i].y) + break; + dispatch->glScissor(pbox->x1, + points[i].y + y_off, + pbox->x2 - pbox->x1, 1); + dispatch->glEnable(GL_SCISSOR_TEST); + dispatch->glRasterPos2i(points[i].x + x_off, + points[i].y + y_off); + dispatch->glDrawPixels(widths[i], 1, format, + type, drawpixels_src); + } + drawpixels_src += + PixmapBytePad(widths[i], drawable->depth); + } + glamor_set_planemask(dest_pixmap, ~0); + glamor_set_alu(dispatch, GXcopy); + dispatch->glDisable(GL_SCISSOR_TEST); + return; + fail: + + 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); + glamor_finish_access(drawable); + } } diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 687cc6a41..bd5192c0a 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -39,43 +39,49 @@ void glamor_init_tile_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - const char *tile_vs = - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord0;\n" - "varying vec2 tile_texture;\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - " tile_texture = v_texcoord0.xy;\n" - "}\n"; - const char *tile_fs = - GLAMOR_DEFAULT_PRECISION - "varying vec2 tile_texture;\n" - "uniform sampler2D sampler;\n" - "void main()\n" - "{\n" - " gl_FragColor = texture2D(sampler, tile_texture);\n" - "}\n"; - GLint fs_prog, vs_prog; - GLint sampler_uniform_location; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + const char *tile_vs = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "varying vec2 tile_texture;\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " tile_texture = v_texcoord0.xy;\n" "}\n"; + const char *tile_fs = + GLAMOR_DEFAULT_PRECISION + "varying vec2 tile_texture;\n" + "uniform sampler2D sampler;\n" + "void main()\n" + "{\n" " gl_FragColor = texture2D(sampler, tile_texture);\n" + "}\n"; + GLint fs_prog, vs_prog; + GLint sampler_uniform_location; - glamor_priv->tile_prog = dispatch->glCreateProgram(); - vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs); - fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, tile_fs); - dispatch->glAttachShader(glamor_priv->tile_prog, vs_prog); - dispatch->glAttachShader(glamor_priv->tile_prog, fs_prog); + glamor_priv->tile_prog = dispatch->glCreateProgram(); + vs_prog = + glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs); + fs_prog = + glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + tile_fs); + dispatch->glAttachShader(glamor_priv->tile_prog, vs_prog); + dispatch->glAttachShader(glamor_priv->tile_prog, fs_prog); - dispatch->glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_POS, "v_position"); - dispatch->glBindAttribLocation(glamor_priv->tile_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0"); - glamor_link_glsl_prog(dispatch, glamor_priv->tile_prog); + dispatch->glBindAttribLocation(glamor_priv->tile_prog, + GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->tile_prog, + GLAMOR_VERTEX_SOURCE, + "v_texcoord0"); + glamor_link_glsl_prog(dispatch, glamor_priv->tile_prog); - sampler_uniform_location = - dispatch->glGetUniformLocation(glamor_priv->tile_prog, "sampler"); - dispatch->glUseProgram(glamor_priv->tile_prog); - dispatch->glUniform1i(sampler_uniform_location, 0); - dispatch->glUseProgram(0); + sampler_uniform_location = + dispatch->glGetUniformLocation(glamor_priv->tile_prog, + "sampler"); + dispatch->glUseProgram(glamor_priv->tile_prog); + dispatch->glUniform1i(sampler_uniform_location, 0); + dispatch->glUseProgram(0); } Bool @@ -84,111 +90,124 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, unsigned char alu, unsigned long planemask, int tile_x, int tile_y) { - ScreenPtr screen = pixmap->drawable.pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - int x1 = x; - int x2 = x + width; - int y1 = y; - int y2 = y + height; - int tile_x1 = tile_x; - int tile_x2 = tile_x + width; - int tile_y1 = tile_y; - int tile_y2 = tile_y + height; - float vertices[8]; - float source_texcoords[8]; - GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; - glamor_pixmap_private *src_pixmap_priv; - glamor_pixmap_private *dst_pixmap_priv; + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + int x1 = x; + int x2 = x + width; + int y1 = y; + int y2 = y + height; + int tile_x1 = tile_x; + int tile_x2 = tile_x + width; + int tile_y1 = tile_y; + int tile_y2 = tile_y + height; + float vertices[8]; + float source_texcoords[8]; + GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; + glamor_pixmap_private *src_pixmap_priv; + glamor_pixmap_private *dst_pixmap_priv; - src_pixmap_priv = glamor_get_pixmap_private(tile); - dst_pixmap_priv = glamor_get_pixmap_private(pixmap); + src_pixmap_priv = glamor_get_pixmap_private(tile); + dst_pixmap_priv = glamor_get_pixmap_private(pixmap); - if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) - || ((tile_y != 0) && (tile_y + height > tile->drawable.height))) { - ErrorF("tile_x = %d tile_y = %d \n", tile_x, tile_y); - goto fail; - } - if (glamor_priv->tile_prog == 0) { - glamor_fallback("Tiling unsupported\n"); - goto fail; - } + if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL) + goto fail; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest has no fbo.\n"); - goto fail; - } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { - /* XXX dynamic uploading candidate. */ - glamor_fallback("Non-texture tile pixmap\n"); - goto fail; - } + if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) + || ((tile_y != 0) + && (tile_y + height > tile->drawable.height))) { + ErrorF("tile_x = %d tile_y = %d \n", tile_x, tile_y); + goto fail; + } + if (glamor_priv->tile_prog == 0) { + glamor_fallback("Tiling unsupported\n"); + goto fail; + } - if (!glamor_set_planemask(pixmap, planemask)) { - glamor_fallback("unsupported planemask %lx\n", planemask); - goto fail; - } - if (alu != GXcopy) { - glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); - glamor_validate_pixmap(tile); - } - - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - glamor_validate_pixmap(pixmap); - pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + glamor_fallback("dest has no fbo.\n"); + goto fail; + } + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { + /* XXX dynamic uploading candidate. */ + glamor_fallback("Non-texture tile pixmap\n"); + goto fail; + } - glamor_set_alu(dispatch, alu); + if (!glamor_set_planemask(pixmap, planemask)) { + glamor_fallback("unsupported planemask %lx\n", planemask); + goto fail; + } + if (alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); + glamor_validate_pixmap(tile); + } - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - dispatch->glUseProgram(glamor_priv->tile_prog); - - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(pixmap); + pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + + glamor_set_alu(dispatch, alu); + + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, + &src_yscale); + dispatch->glUseProgram(glamor_priv->tile_prog); + + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, + src_pixmap_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - glamor_set_normalize_tcoords(src_xscale, src_yscale, - tile_x1, tile_y1, - tile_x2, tile_y2, - glamor_priv->yInverted, - source_texcoords); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - source_texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - } - else { - GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, src_pixmap_priv); - } - - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, - x1, y1,x2, y2, - glamor_priv->yInverted, - vertices); + glamor_set_normalize_tcoords(src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + source_texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + } else { + GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, + src_pixmap_priv); + } - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glamor_set_normalize_vcoords(dst_xscale, dst_yscale, + x1, y1, x2, y2, + glamor_priv->yInverted, vertices); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - } - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(pixmap, ~0); - return TRUE; + } + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + glamor_set_alu(dispatch, GXcopy); + glamor_set_planemask(pixmap, ~0); + return TRUE; -fail: - return FALSE; + fail: + return FALSE; } diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c index 168d485f0..3cbdd55a8 100644 --- a/glamor/glamor_triangles.c +++ b/glamor/glamor_triangles.c @@ -33,29 +33,24 @@ #include "glamor_priv.h" void -glamor_triangles (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int ntris, - xTriangle *tris) -{ +glamor_triangles(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris) +{ - if (glamor_prepare_access(pDst->pDrawable, GLAMOR_ACCESS_RW)) { - if (pSrc->pDrawable == NULL || - glamor_prepare_access(pSrc->pDrawable, GLAMOR_ACCESS_RO)) - { + if (glamor_prepare_access(pDst->pDrawable, GLAMOR_ACCESS_RW)) { + if (pSrc->pDrawable == NULL || + glamor_prepare_access(pSrc->pDrawable, + GLAMOR_ACCESS_RO)) { - fbTriangles(op, - pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris); - } - if (pSrc->pDrawable != NULL) - glamor_finish_access(pSrc->pDrawable); + fbTriangles(op, pSrc, pDst, maskFormat, xSrc, + ySrc, ntris, tris); + } + if (pSrc->pDrawable != NULL) + glamor_finish_access(pSrc->pDrawable); - glamor_finish_access(pDst->pDrawable); + glamor_finish_access(pDst->pDrawable); } } - - diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index fe5bd4e1e..265d9ed5c 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -7,8 +7,8 @@ #define v_from_x_coord_x(_xscale_, _x_) ( 2 * (_x_) * (_xscale_) - 1.0) #define v_from_x_coord_y(_yscale_, _y_) (-2 * (_y_) * (_yscale_) + 1.0) -#define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0) -#define t_from_x_coord_x(_xscale_, _x_) ((_x_) * (_xscale_)) +#define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0) +#define t_from_x_coord_x(_xscale_, _x_) ((_x_) * (_xscale_)) #define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_)) #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) @@ -17,7 +17,7 @@ *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width; \ *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height; \ } while(0) - + #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \ + ((float)xFixedFrac(_val_) / 65536.0)) @@ -124,40 +124,38 @@ inline static void glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) { - int x_min, y_min; - int x_max, y_max; - int i; - x_min = y_min = MAXSHORT; - x_max = y_max = MINSHORT; - for(i = 0; i < nbox; i++) - { - if (x_min > boxes[i].x1) - x_min = boxes[i].x1; - if (y_min > boxes[i].y1) - y_min = boxes[i].y1; + int x_min, y_min; + int x_max, y_max; + int i; + x_min = y_min = MAXSHORT; + x_max = y_max = MINSHORT; + for (i = 0; i < nbox; i++) { + if (x_min > boxes[i].x1) + x_min = boxes[i].x1; + if (y_min > boxes[i].y1) + y_min = boxes[i].y1; - if (x_max < boxes[i].x2) - x_max = boxes[i].x2; - if (y_max < boxes[i].y2) - y_max = boxes[i].y2; - } - bound->x1 = x_min; - bound->y1 = y_min; - bound->x2 = x_max; - bound->y2 = y_max; + if (x_max < boxes[i].x2) + x_max = boxes[i].x2; + if (y_max < boxes[i].y2) + y_max = boxes[i].y2; + } + bound->x1 = x_min; + bound->y1 = y_min; + bound->x2 = x_max; + bound->y2 = y_max; } -inline static void +inline static void glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) { - int i; - for (i = 0; i < nbox; i++) - { - boxes[i].x1 += dx; - boxes[i].y1 += dy; - boxes[i].x2 += dx; - boxes[i].y2 += dy; - } + int i; + for (i = 0; i < nbox; i++) { + boxes[i].x1 += dx; + boxes[i].y1 += dy; + boxes[i].x2 += dx; + boxes[i].y2 += dy; + } } #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) @@ -195,7 +193,7 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) _pixmap_priv_->pending_op.fill.color4fv); \ } \ } while(0) - + /** * Borrow from uxa. @@ -203,34 +201,42 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) 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; + 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; + case 30: + return PICT_x2r10g10b10; #endif - case 32: return PICT_a8r8g8b8; - } + case 32: + return PICT_a8r8g8b8; + } } static inline CARD32 format_for_pixmap(PixmapPtr pixmap) { - glamor_pixmap_private *pixmap_priv; - PictFormatShort pict_format; + 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); + 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; + return pict_format; } /* @@ -240,298 +246,299 @@ format_for_pixmap(PixmapPtr pixmap) * Return 0 if find a matched texture type. Otherwise return -1. **/ #ifndef GLAMOR_GLES2 -static inline int +static inline int glamor_get_tex_format_type_from_pictformat(PictFormatShort format, - GLenum *tex_format, - GLenum *tex_type, - int *no_alpha, - int *no_revert) + GLenum * tex_format, + GLenum * tex_type, + int *no_alpha, int *no_revert) { - *no_alpha = 0; - *no_revert = 1; - switch (format) { - case PICT_a1: - *tex_format = GL_COLOR_INDEX; - *tex_type = GL_BITMAP; - break; - case PICT_b8g8r8x8: - *no_alpha = 1; - case PICT_b8g8r8a8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8; - break; + *no_alpha = 0; + *no_revert = 1; + switch (format) { + case PICT_a1: + *tex_format = GL_COLOR_INDEX; + *tex_type = GL_BITMAP; + break; + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8; + break; - case PICT_x8r8g8b8: - *no_alpha = 1; - case PICT_a8r8g8b8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case PICT_x8b8g8r8: - *no_alpha = 1; - case PICT_a8b8g8r8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case PICT_x2r10g10b10: - *no_alpha = 1; - case PICT_a2r10g10b10: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; - break; - case PICT_x2b10g10r10: - *no_alpha = 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: - *no_alpha = 1; - case PICT_a1b5g5r5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - - case PICT_x1r5g5b5: - *no_alpha = 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: - *no_alpha = 1; - case PICT_a4r4g4b4: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - break; + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + case PICT_x2b10g10r10: + *no_alpha = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; + break; - case PICT_x4b4g4r4: - *no_alpha = 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; + 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: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + + case PICT_x1r5g5b5: + *no_alpha = 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: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + + case PICT_x4b4g4r4: + *no_alpha = 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; } #else #define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) -static inline int +static inline int glamor_get_tex_format_type_from_pictformat(PictFormatShort format, - GLenum *tex_format, - GLenum *tex_type, - int *no_alpha, - int *no_revert) + GLenum * tex_format, + GLenum * tex_type, + int *no_alpha, int *no_revert) { - *no_alpha = 0; - *no_revert = IS_LITTLE_ENDIAN; + *no_alpha = 0; + *no_revert = IS_LITTLE_ENDIAN; - switch (format) { - case PICT_b8g8r8x8: - *no_alpha = 1; - case PICT_b8g8r8a8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_BYTE; - *no_revert = !IS_LITTLE_ENDIAN; - break; + switch (format) { + case PICT_b8g8r8x8: + *no_alpha = 1; + case PICT_b8g8r8a8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_BYTE; + *no_revert = !IS_LITTLE_ENDIAN; + break; - case PICT_x8r8g8b8: - *no_alpha = 1; - case PICT_a8r8g8b8: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_BYTE; - break; + case PICT_x8r8g8b8: + *no_alpha = 1; + case PICT_a8r8g8b8: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_BYTE; + break; - case PICT_x8b8g8r8: - *no_alpha = 1; - case PICT_a8b8g8r8: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_BYTE; - break; + case PICT_x8b8g8r8: + *no_alpha = 1; + case PICT_a8b8g8r8: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_BYTE; + break; - case PICT_x2r10g10b10: - *no_alpha = 1; - case PICT_a2r10g10b10: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *no_revert = TRUE; - break; + case PICT_x2r10g10b10: + *no_alpha = 1; + case PICT_a2r10g10b10: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_INT_10_10_10_2; + *no_revert = TRUE; + break; - case PICT_x2b10g10r10: - *no_alpha = 1; - case PICT_a2b10g10r10: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *no_revert = TRUE; - break; - - case PICT_r5g6b5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *no_revert = TRUE; - break; + case PICT_x2b10g10r10: + *no_alpha = 1; + case PICT_a2b10g10r10: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_INT_10_10_10_2; + *no_revert = TRUE; + break; - case PICT_b5g6r5: - *tex_format = GL_RGB; - *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *no_revert = FALSE; - break; + case PICT_r5g6b5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *no_revert = TRUE; + break; - case PICT_x1b5g5r5: - *no_alpha = 1; - case PICT_a1b5g5r5: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *no_revert = TRUE; - break; - - case PICT_x1r5g5b5: - *no_alpha = 1; - case PICT_a1r5g5b5: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *no_revert = TRUE; - break; + case PICT_b5g6r5: + *tex_format = GL_RGB; + *tex_type = GL_UNSIGNED_SHORT_5_6_5; + *no_revert = FALSE; + break; - case PICT_a8: - *tex_format = GL_ALPHA; - *tex_type = GL_UNSIGNED_BYTE; - *no_revert = TRUE; - break; + case PICT_x1b5g5r5: + *no_alpha = 1; + case PICT_a1b5g5r5: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + *no_revert = TRUE; + break; - case PICT_x4r4g4b4: - *no_alpha = 1; - case PICT_a4r4g4b4: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - *no_revert = TRUE; - break; + case PICT_x1r5g5b5: + *no_alpha = 1; + case PICT_a1r5g5b5: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + *no_revert = TRUE; + break; - case PICT_x4b4g4r4: - *no_alpha = 1; - case PICT_a4b4g4r4: - *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - *no_revert = TRUE; - break; - - default: - LogMessageVerb(X_INFO, 0, "fail to get matched format for %x \n", format); - return -1; - } - return 0; + case PICT_a8: + *tex_format = GL_ALPHA; + *tex_type = GL_UNSIGNED_BYTE; + *no_revert = TRUE; + break; + + case PICT_x4r4g4b4: + *no_alpha = 1; + case PICT_a4r4g4b4: + *tex_format = GL_BGRA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + *no_revert = TRUE; + break; + + case PICT_x4b4g4r4: + *no_alpha = 1; + case PICT_a4b4g4r4: + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; + *no_revert = TRUE; + break; + + default: + LogMessageVerb(X_INFO, 0, + "fail to get matched format for %x \n", + format); + return -1; + } + return 0; } #endif -static inline int +static inline int glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, - GLenum *format, - GLenum *type, - int *no_alpha, - int *no_revert) + GLenum * format, + GLenum * type, + int *no_alpha, int *no_revert) { - glamor_pixmap_private *pixmap_priv; - PictFormatShort pict_format; + 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); + 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, - no_alpha, no_revert); + return glamor_get_tex_format_type_from_pictformat(pict_format, + format, type, + no_alpha, + no_revert); } /* borrowed from uxa */ static inline Bool glamor_get_rgba_from_pixel(CARD32 pixel, - float * red, - float * green, - float * blue, - float * alpha, - CARD32 format) + float *red, + float *green, + float *blue, float *alpha, CARD32 format) { - int rbits, bbits, gbits, abits; - int rshift, bshift, gshift, ashift; + 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); + 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 (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; + } 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; - } + } else { + return FALSE; + } #define COLOR_INT_TO_FLOAT(_fc_, _p_, _s_, _bits_) \ *_fc_ = (((_p_) >> (_s_)) & (( 1 << (_bits_)) - 1)) \ - / (float)((1<<(_bits_)) - 1) + / (float)((1<<(_bits_)) - 1) - if (rbits) - COLOR_INT_TO_FLOAT(red, pixel, rshift, rbits); - else - *red = 0; + 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 (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 (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; + if (abits) + COLOR_INT_TO_FLOAT(alpha, pixel, ashift, abits); + else + *alpha = 1; - return TRUE; + return TRUE; } diff --git a/glamor/glamor_window.c b/glamor/glamor_window.c index 05555b204..f6e4cd175 100644 --- a/glamor/glamor_window.c +++ b/glamor/glamor_window.c @@ -34,41 +34,42 @@ static void -glamor_fixup_window_pixmap(DrawablePtr pDrawable, PixmapPtr *ppPixmap) +glamor_fixup_window_pixmap(DrawablePtr pDrawable, PixmapPtr * ppPixmap) { - PixmapPtr pPixmap = *ppPixmap; - glamor_pixmap_private *pixmap_priv; + PixmapPtr pPixmap = *ppPixmap; + glamor_pixmap_private *pixmap_priv; - if (pPixmap->drawable.bitsPerPixel != pDrawable->bitsPerPixel) - { - pixmap_priv = glamor_get_pixmap_private(pPixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("pixmap %p has no fbo\n", pPixmap); - goto fail; - } - glamor_debug_output(GLAMOR_DEBUG_UNIMPL, "To be implemented.\n"); - } - return; + if (pPixmap->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { + pixmap_priv = glamor_get_pixmap_private(pPixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + glamor_fallback("pixmap %p has no fbo\n", pPixmap); + goto fail; + } + glamor_debug_output(GLAMOR_DEBUG_UNIMPL, + "To be implemented.\n"); + } + return; -fail: - GLAMOR_PANIC(" We can't fall back to fbFixupWindowPixmap, as the fb24_32ReformatTile" - " is broken for glamor. \n"); + fail: + GLAMOR_PANIC + (" We can't fall back to fbFixupWindowPixmap, as the fb24_32ReformatTile" + " is broken for glamor. \n"); } Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask) { - if (mask & CWBackPixmap) { - if (pWin->backgroundState == BackgroundPixmap) - glamor_fixup_window_pixmap(&pWin->drawable, &pWin->background.pixmap); - } + if (mask & CWBackPixmap) { + if (pWin->backgroundState == BackgroundPixmap) + glamor_fixup_window_pixmap(&pWin->drawable, + &pWin-> + background.pixmap); + } - if (mask & CWBorderPixmap) { - if (pWin->borderIsPixel == FALSE) - glamor_fixup_window_pixmap(&pWin->drawable, &pWin->border.pixmap); - } - return TRUE; + if (mask & CWBorderPixmap) { + if (pWin->borderIsPixel == FALSE) + glamor_fixup_window_pixmap(&pWin->drawable, + &pWin->border.pixmap); + } + return TRUE; } - - - From ba1b3b53240b5d499791570ba9f598a4e421c719 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 9 Nov 2011 16:09:03 +0800 Subject: [PATCH 227/462] Add new version glamor_fillspans without internal fallback. For the purpose of incrementally intergration of existing intel driver, for the GC operations we may don't want to use glamor's internal fallback which is in general much slower than the implementation in intel driver. If the parameter "fallback" is false when call the glamor_fillspans, then if glamor found it can't accelerate it then it will just return a FALSE rather than fallback to a slow path. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 7 +++++++ glamor/glamor_fill.c | 5 +++-- glamor/glamor_fillspans.c | 33 ++++++++++++++++++++++++++++----- glamor/glamor_glyphs.c | 2 +- glamor/glamor_polyfillrect.c | 2 +- glamor/glamor_priv.h | 2 +- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index f9da4ade8..e98d7d5a5 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -79,3 +79,10 @@ extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); #endif + +extern _X_EXPORT Bool glamor_fill_spans_nf(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, + int *widths, int sorted); + + diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 7a4325146..5fc350ba8 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -34,7 +34,7 @@ Bool glamor_fill(DrawablePtr drawable, - GCPtr gc, int x, int y, int width, int height) + GCPtr gc, int x, int y, int width, int height, Bool fallback) { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); int off_x, off_y; @@ -80,7 +80,9 @@ glamor_fill(DrawablePtr drawable, break; } return TRUE; + fail: + if (!fallback) return FALSE; if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { fbFill(drawable, gc, x, y, width, height); @@ -89,7 +91,6 @@ glamor_fill(DrawablePtr drawable, glamor_finish_access(drawable); } return TRUE; - } void diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index a91e6a96a..996f0c5e8 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -30,10 +30,10 @@ */ #include "glamor_priv.h" -void -glamor_fill_spans(DrawablePtr drawable, +static Bool +_glamor_fill_spans(DrawablePtr drawable, GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted) + int n, DDXPointPtr points, int *widths, int sorted, Bool fallback) { DDXPointPtr ppt; int nbox; @@ -66,12 +66,15 @@ glamor_fill_spans(DrawablePtr drawable, if (x2 <= x1) continue; - glamor_fill(drawable, gc, x1, y, x2 - x1, 1); + if (!glamor_fill(drawable, gc, x1, y, x2 - x1, 1, fallback)) + goto fail; pbox++; } } - return; + return TRUE; + fail: + if (!fallback) return FALSE; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { @@ -82,4 +85,24 @@ glamor_fill_spans(DrawablePtr drawable, } glamor_finish_access(drawable); } + return TRUE; } + + +void +glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + _glamor_fill_spans(drawable, gc, n, points, widths, sorted, TRUE); +} + +Bool +glamor_fill_spans_nf(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + return _glamor_fill_spans(drawable, gc, n, points, widths, sorted, FALSE); +} + + diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 899dd9d8c..335540d92 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -690,7 +690,7 @@ glamor_glyphs_via_mask(CARD8 op, } gc = GetScratchGC(mask_pixmap->drawable.depth, screen); ValidateGC(&mask_pixmap->drawable, gc); - glamor_fill(&mask_pixmap->drawable, gc, 0, 0, width, height); + glamor_fill(&mask_pixmap->drawable, gc, 0, 0, width, height, TRUE); FreeScratchGC(gc); x = -extents.x1; y = -extents.y1; diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 762dfc255..eff63b6c0 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -87,7 +87,7 @@ glamor_poly_fill_rect(DrawablePtr drawable, if (x1 >= x2 || y1 >= y2) continue; if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, - y2 - y1)) + y2 - y1, TRUE)) goto fail; } } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 66c43591d..a40a508d2 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -370,7 +370,7 @@ int glamor_gl_get_version(void); /* glamor_fill.c */ Bool glamor_fill(DrawablePtr drawable, - GCPtr gc, int x, int y, int width, int height); + GCPtr gc, int x, int y, int width, int height, Bool fallback); Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel); From 9b6a484df0724d72dd27ad620672e7a762a460df Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 11 Nov 2011 10:26:00 +0800 Subject: [PATCH 228/462] Add new version glamor_poly_fill_rect without internal fallback. If need fallback, this new version just returns FALSE without doing anything. It's the caller's responsibility to implement fallback method. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 4 ++++ glamor/glamor_fill.c | 2 +- glamor/glamor_polyfillrect.c | 28 ++++++++++++++++++++++------ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index e98d7d5a5..ce1a41f9f 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -85,4 +85,8 @@ extern _X_EXPORT Bool glamor_fill_spans_nf(DrawablePtr drawable, int n, DDXPointPtr points, int *widths, int sorted); +extern _X_EXPORT Bool glamor_poly_fill_rect_nf(DrawablePtr drawable, + GCPtr gc, + int nrect, + xRectangle * prect); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 5fc350ba8..b20ec5e39 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -144,7 +144,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat color[4]; float vertices[8]; GLfloat xscale, yscale; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("dest %p has no fbo.\n", pixmap); goto fail; } diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index eff63b6c0..44df8a80f 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -37,9 +37,9 @@ * GC PolyFillRect implementation, taken straight from fb_fill.c */ -void -glamor_poly_fill_rect(DrawablePtr drawable, - GCPtr gc, int nrect, xRectangle * prect) +static Bool +_glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle * prect, Bool fallback) { int fullX1, fullX2, fullY1, fullY2; int xorg, yorg; @@ -87,13 +87,14 @@ glamor_poly_fill_rect(DrawablePtr drawable, if (x1 >= x2 || y1 >= y2) continue; if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, - y2 - y1, TRUE)) + y2 - y1, fallback)) goto fail; } } - return; + return TRUE; fail: + if (!fallback) return FALSE; glamor_fallback(" to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { @@ -103,5 +104,20 @@ glamor_poly_fill_rect(DrawablePtr drawable, } glamor_finish_access(drawable); } - return; + return TRUE; +} + + +void +glamor_poly_fill_rect(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle * prect) +{ + _glamor_poly_fill_rect(drawable, gc, nrect, prect, TRUE); +} + +Bool +glamor_poly_fill_rect_nf(DrawablePtr drawable, + GCPtr gc, int nrect, xRectangle * prect) +{ + return _glamor_poly_fill_rect(drawable, gc, nrect, prect, FALSE); } From 13ab4d59afb824f2a4c03280fffe79c6ba9aa26c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 11 Nov 2011 14:55:12 +0800 Subject: [PATCH 229/462] Disable glamor_tile temporary. Enable glamor tile cause corrupted output. Need more investigation. Signed-off-by: Zhigang Gong --- glamor/glamor_tile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index bd5192c0a..77f4d0e1c 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -110,6 +110,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); + goto fail; if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL) goto fail; From 9ff39e53eb20673d42f42c94adb55bf9a9f1c285 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 15 Nov 2011 20:16:16 +0800 Subject: [PATCH 230/462] Revert "Disable glamor_tile temporary." The previous corruption output is caused by GLAMOR/UXA flushing issue. Now get fixed. This reverts commit 0d2d3e4f051e48c3499e1c972e012803a8623526. --- glamor/glamor_tile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 77f4d0e1c..bd5192c0a 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -110,7 +110,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); - goto fail; if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL) goto fail; From 90eaac96aeb53b3e45b82dc7dd4e98778c8c9343 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 15 Nov 2011 20:17:18 +0800 Subject: [PATCH 231/462] If caller is not using glamor screen, we can't register the block handler. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index c96795ced..b660f95e9 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -334,16 +334,16 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); - if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, - _glamor_wakeup_handler, - (void *) - &glamor_priv->dispatch)) { - goto fail; - } - glamor_set_debug_level(&glamor_debug_level); if (flags & GLAMOR_USE_SCREEN) { + if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, + _glamor_wakeup_handler, + (void *) + &glamor_priv->dispatch)) { + goto fail; + } + glamor_priv->saved_close_screen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; From 7b2310834d83198fc88b5a5fb062cb1c9ee19ead Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 22 Nov 2011 18:28:10 +0800 Subject: [PATCH 232/462] Added a missed header file. Pointed by Chris, we must add xorg-server.h at the top of each file before we include any other xorg header files. Otherwise, it may cause incorrect XID length. This commit also fixes one compilation warning in X86_64 platform. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 9e4804ab4..a068e39a6 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -30,6 +30,7 @@ #ifdef HAVE_DIX_CONFIG_H #include #endif +#include #include #include #include @@ -129,7 +130,7 @@ _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, image = glamor_egl->egl_create_image_khr(glamor_egl->display, glamor_egl->context, EGL_DRM_BUFFER_MESA, - (void *) name, attribs); + (void *) (uintptr_t)name, attribs); if (image == EGL_NO_IMAGE_KHR) return EGL_NO_IMAGE_KHR; From b5480e64ac4a72bdc31e587ff9e51d67a1a0f11d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 9 Dec 2011 14:57:24 +0800 Subject: [PATCH 233/462] Override create/destroy picture to track pict format. When create a piccture, we need to attach a pixmap to it. A pixmap only has a depth, which is not sufficant for glamor. As in openGL texture only has a few internal formats which is not sufficant to represent all the possible picture format. So we always transform the picture format to GL_RGBA. And when we need to read back the picture, we must know the original picture format. So we have to override create and destroy picture to track a pixmap's real picture format if it is attached to a picture. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index b660f95e9..482a07416 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -388,16 +388,14 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_triangles = ps->Triangles; ps->Triangles = glamor_triangles; - glamor_priv->saved_create_picture = ps->CreatePicture; - ps->CreatePicture = glamor_create_picture; - - glamor_priv->saved_destroy_picture = ps->DestroyPicture; - ps->DestroyPicture = glamor_destroy_picture; - glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph; ps->UnrealizeGlyph = glamor_glyph_unrealize; } + glamor_priv->saved_create_picture = ps->CreatePicture; + ps->CreatePicture = glamor_create_picture; + glamor_priv->saved_destroy_picture = ps->DestroyPicture; + ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); #endif glamor_init_solid_shader(screen); From b5630663cf9438383166f59cdfc7889571f2cd62 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 9 Dec 2011 15:58:19 +0800 Subject: [PATCH 234/462] exports more rendering functions to DDX driver. Exports all necessary rendering functions to DDx drivers, including CopyArea, Glyphs, Composite, Triangles, .... Signed-off-by: Zhigang Gong --- glamor/glamor.h | 52 ++++++++++++++ glamor/glamor_copyarea.c | 67 ++++++++++++++---- glamor/glamor_core.c | 2 +- glamor/glamor_getspans.c | 1 + glamor/glamor_glyphs.c | 106 +++++++++++++---------------- glamor/glamor_picture.c | 16 +++-- glamor/glamor_pixmap.c | 6 +- glamor/glamor_priv.h | 2 +- glamor/glamor_putimage.c | 35 +++++++--- glamor/glamor_render.c | 140 +++++++++++++++++++++++++++----------- glamor/glamor_triangles.c | 33 +++++++-- 11 files changed, 327 insertions(+), 133 deletions(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index ce1a41f9f..fd056e96a 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -90,3 +90,55 @@ extern _X_EXPORT Bool glamor_poly_fill_rect_nf(DrawablePtr drawable, int nrect, xRectangle * prect); +extern _X_EXPORT Bool glamor_put_image_nf(DrawablePtr drawable, + GCPtr gc, int depth, int x, int y, + int w, int h, int left_pad, + int image_format, char *bits); + +extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure); + +extern _X_EXPORT Bool glamor_composite_nf(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height); + +extern _X_EXPORT Bool glamor_trapezoids_nf(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps); + +extern _X_EXPORT Bool glamor_glyphs_nf(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, + GlyphListPtr list, GlyphPtr * glyphs); + +extern _X_EXPORT Bool glamor_triangles_nf(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, + int ntris, xTriangle * tris); + + +extern _X_EXPORT void glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph); + + diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index b49d8163f..38254d6fc 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -286,16 +286,17 @@ glamor_copy_n_to_n_textured(DrawablePtr src, return FALSE; } -void -glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, void *closure) +static Bool +_glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure, Bool fallback) { glamor_access_t dst_access; PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; @@ -308,6 +309,7 @@ glamor_copy_n_to_n(DrawablePtr src, int src_x_off, src_y_off, dst_x_off, dst_y_off; int i; int overlaped = 0; + Bool ret = TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); @@ -315,6 +317,9 @@ glamor_copy_n_to_n(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; + if (!dst_pixmap_priv || !src_pixmap_priv) + goto fail; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); @@ -338,14 +343,12 @@ glamor_copy_n_to_n(DrawablePtr src, } } /* XXX need revisit to handle overlapped area copying. */ - #ifndef GLAMOR_GLES2 if ((overlaped || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { goto done; - return; } #endif glamor_calculate_boxes_bound(&bound, box, nbox); @@ -394,6 +397,12 @@ glamor_copy_n_to_n(DrawablePtr src, fail: + + if (!fallback) { + ret = FALSE; + goto done; + } + glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); @@ -424,6 +433,7 @@ glamor_copy_n_to_n(DrawablePtr src, if (temp_src != src) { (*screen->DestroyPixmap) (temp_pixmap); } + return ret; } RegionPtr @@ -438,3 +448,36 @@ glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, return region; } + +void +glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure) +{ + _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, + dy, reverse, upsidedown, bitplane, closure, TRUE); +} + +Bool +glamor_copy_n_to_n_nf(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure) +{ + return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, + dy, reverse, upsidedown, bitplane, closure, FALSE); +} + diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 8ba938fe3..4c58022a8 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -264,7 +264,7 @@ glamor_finish_access(DrawablePtr drawable) glamor_get_screen_private(drawable->pScreen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return; if (pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 96f51201b..dff55ba73 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -104,3 +104,4 @@ glamor_get_spans(DrawablePtr drawable, glamor_finish_access(drawable); } } + diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 335540d92..96e4c57ec 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -239,57 +239,9 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, ValidateGC(&pCachePixmap->drawable, gc); scratch = pGlyphPixmap; -#if 0 - /* Create a temporary bo to stream the updates to the cache */ - if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth || - !uxa_pixmap_is_offscreen(scratch)) { - scratch = screen->CreatePixmap(screen, - glyph->info.width, - glyph->info.height, - pCachePixmap-> - drawable.depth, 0); - if (scratch) { - if (pGlyphPixmap->drawable.depth != - pCachePixmap->drawable.depth) { - PicturePtr picture; - int error; - - picture = - CreatePicture(0, - &scratch->drawable, - PictureMatchFormat - (screen, - pCachePixmap-> - drawable.depth, - cache->picture->format), - 0, NULL, serverClient, - &error); - if (picture) { - ValidatePicture(picture); - uxa_composite(PictOpSrc, - pGlyphPicture, - NULL, picture, - 0, 0, 0, 0, 0, - 0, - glyph->info.width, - glyph->info.height); - FreePicture(picture, 0); - } - } else { - glamor_copy_area(&pGlyphPixmap->drawable, - &scratch->drawable, - gc, 0, 0, - glyph->info.width, - glyph->info.height, 0, 0); - } - } else { - scratch = pGlyphPixmap; - } - } -#endif - glamor_copy_area(&scratch->drawable, &pCachePixmap->drawable, gc, - 0, 0, glyph->info.width, glyph->info.height, x, - y); + (*gc->ops->CopyArea)(&scratch->drawable, &pCachePixmap->drawable, gc, + 0, 0, glyph->info.width, glyph->info.height, x, + y); if (scratch != pGlyphPixmap) screen->DestroyPixmap(scratch); @@ -657,6 +609,7 @@ glamor_glyphs_via_mask(CARD8 op, BoxRec extents = { 0, 0, 0, 0 }; CARD32 component_alpha; glamor_glyph_buffer_t buffer; + xRectangle fill_rect; GCPtr gc; @@ -690,7 +643,14 @@ glamor_glyphs_via_mask(CARD8 op, } gc = GetScratchGC(mask_pixmap->drawable.depth, screen); ValidateGC(&mask_pixmap->drawable, gc); - glamor_fill(&mask_pixmap->drawable, gc, 0, 0, width, height, TRUE); + gc->fillStyle = FillSolid; + //glamor_fill(&mask_pixmap->drawable, gc, 0, 0, width, height, TRUE); + fill_rect.x = 0; + fill_rect.y = 0; + fill_rect.width = width; + fill_rect.height = height; + gc->ops->PolyFillRect(&mask_pixmap->drawable, gc, 1, &fill_rect); + FreeScratchGC(gc); x = -extents.x1; y = -extents.y1; @@ -810,13 +770,14 @@ glamor_glyphs_to_dst(CARD8 op, x_src, y_src, x_dst, y_dst); } -void -glamor_glyphs(CARD8 op, - PicturePtr src, - PicturePtr dst, - PictFormatPtr mask_format, - INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +static Bool +_glamor_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, GlyphListPtr list, + GlyphPtr * glyphs, Bool fallback) { /* If we don't have a mask format but all the glyphs have the same format * and don't intersect, use the glyph format as mask format for the full @@ -848,4 +809,31 @@ glamor_glyphs(CARD8 op, else glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, list, glyphs); + return TRUE; } + +void +glamor_glyphs(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + _glamor_glyphs(op, src, dst, mask_format, x_src, + y_src, nlist, list, glyphs, TRUE); +} + +Bool +glamor_glyphs_nf(CARD8 op, + PicturePtr src, + PicturePtr dst, + PictFormatPtr mask_format, + INT16 x_src, + INT16 y_src, int nlist, + GlyphListPtr list, GlyphPtr * glyphs) +{ + return _glamor_glyphs(op, src, dst, mask_format, x_src, + y_src, nlist, list, glyphs, FALSE); +} + diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 9e8d6ec80..68c90eb7a 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -60,10 +60,11 @@ glamor_create_picture(PicturePtr picture) 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; + + if (pixmap_priv) { + pixmap_priv->is_picture = 1; + pixmap_priv->pict_format = picture->format; + } return glamor_priv->saved_create_picture(picture); } @@ -81,10 +82,11 @@ glamor_destroy_picture(PicturePtr picture) 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; + if (pixmap_priv) { + pixmap_priv->is_picture = 0; + pixmap_priv->pict_format = 0; + } glamor_priv->saved_destroy_picture(picture); } diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index f02acc746..6f44aabd3 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -302,6 +302,9 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLuint tex; int need_flip; + + if (!pixmap_priv) + return; need_flip = (flip && !glamor_priv->yInverted); /* Try fast path firstly, upload the pixmap to the texture attached @@ -368,7 +371,6 @@ glamor_pixmap_ensure_fb(PixmapPtr pixmap) glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - if (pixmap_priv->fb == 0) dispatch->glGenFramebuffers(1, &pixmap_priv->fb); assert(pixmap_priv->tex != 0); @@ -644,7 +646,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; screen = pixmap->drawable.pScreen; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index a40a508d2..4dfdbc456 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -545,7 +545,7 @@ glamor_picture_format_fixup(PicturePtr picture, * fallback the whole process to cpu. Most of the time, * this will increase performance obviously. */ -#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD +//#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD //#define GLAMOR_DELAYED_FILLING diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index a8cafed52..989f635da 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -240,9 +240,9 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, #endif -void -glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, - int w, int h, int left_pad, int image_format, char *bits) +static Bool +_glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, + int w, int h, int left_pad, int image_format, char *bits, Bool fallback) { glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); @@ -263,10 +263,9 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (image_format == XYBitmap) { assert(depth == 1); goto fail; - return; } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("has no fbo.\n"); goto fail; } @@ -309,12 +308,12 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, pixmap->drawable.bitsPerPixel); } else { dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); -// dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } dispatch->glGenTextures(1, &tex); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { iformat = format; } else { @@ -328,10 +327,10 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUniform1i(glamor_priv-> finish_access_no_revert[no_alpha], @@ -386,15 +385,17 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glUseProgram(0); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDeleteTextures(1, &tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); - return; + return TRUE; fail: glamor_set_planemask(pixmap, ~0); + if (!fallback) return FALSE; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { @@ -402,4 +403,22 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, left_pad, image_format, bits); glamor_finish_access(&pixmap->drawable); } + return TRUE; } + +void +glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, + int w, int h, int left_pad, int image_format, char *bits) +{ + _glamor_put_image(drawable, gc, depth, x, y, w, h, + left_pad, image_format, bits, TRUE); +} + +Bool +glamor_put_image_nf(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, + int w, int h, int left_pad, int image_format, char *bits) +{ + return _glamor_put_image(drawable, gc, depth, x, y, w, h, + left_pad, image_format, bits, FALSE); +} + diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 7f52c7b34..e7e53053c 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -36,8 +36,6 @@ #include "mipict.h" #include "fbpict.h" -//#include "glu3/glu3.h" - struct shader_key { enum shader_source source; enum shader_mask mask; @@ -371,6 +369,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glamor_pixmap_private * pixmap_priv) { + unsigned int no_alpha, no_revert, format, type; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; @@ -497,6 +496,7 @@ glamor_composite_with_copy(CARD8 op, INT16 y_dest, CARD16 width, CARD16 height) { RegionRec region; + int ret; if (!source->pDrawable) return FALSE; @@ -511,21 +511,22 @@ glamor_composite_with_copy(CARD8 op, 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); + ret = TRUE; + ErrorF("width %d height %d \n", width, height); + if (!glamor_copy_n_to_n_nf(source->pDrawable, + dest->pDrawable, NULL, + REGION_RECTS(®ion), + REGION_NUM_RECTS(®ion), + x_source - x_dest, y_source - y_dest, + FALSE, FALSE, 0, NULL)) + ret = FALSE; REGION_UNINIT(dest->pDrawable->pScreen, ®ion); - return TRUE; + return ret; } static void @@ -696,7 +697,6 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src, return FALSE; } - if (src_type == mask_type) { *des = PICT_VISFORMAT(src_bpp, src_type, new_vis); return TRUE; @@ -753,10 +753,9 @@ glamor_composite_with_shader(CARD8 op, PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; GLfloat source_solid_color[4], mask_solid_color[4]; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + if (!dest_pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; } @@ -997,8 +996,6 @@ glamor_composite_with_shader(CARD8 op, &dest_x_off, &dest_y_off); pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); - - if (glamor_priv->has_source_coords) { glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, @@ -1190,16 +1187,17 @@ glamor_convert_gradient_picture(ScreenPtr screen, return dst; } -void -glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) +static Bool +_glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height, Bool fallback) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_pixmap_private *dest_pixmap_priv; @@ -1214,6 +1212,7 @@ glamor_composite(CARD8 op, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + Bool ret = TRUE; x_temp_src = x_source; y_temp_src = y_source; @@ -1222,7 +1221,7 @@ glamor_composite(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + if (!dest_pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { goto fail; } @@ -1231,13 +1230,14 @@ glamor_composite(CARD8 op, glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (!source_pixmap_priv) goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + if (!mask_pixmap_priv) goto fail; } - if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable @@ -1311,7 +1311,6 @@ glamor_composite(CARD8 op, goto fail; } } - if (!mask) { if (glamor_composite_with_copy(op, temp_src, dest, x_temp_src, y_temp_src, @@ -1319,7 +1318,6 @@ glamor_composite(CARD8 op, height)) goto done; } - rect.x_src = x_temp_src; rect.y_src = y_temp_src; rect.x_mask = x_temp_mask; @@ -1334,6 +1332,12 @@ glamor_composite(CARD8 op, fail: + dispatch->glUseProgram(0); + dispatch->glDisable(GL_BLEND); + if (!fallback) { + ret = FALSE; + goto done; + } glamor_fallback ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", source, source->pDrawable, @@ -1349,8 +1353,6 @@ glamor_composite(CARD8 op, dest->pDrawable->width, dest->pDrawable->height, glamor_get_picture_location(dest)); - dispatch->glUseProgram(0); - dispatch->glDisable(GL_BLEND); if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_picture (source, GLAMOR_ACCESS_RO)) { @@ -1375,8 +1377,45 @@ glamor_composite(CARD8 op, FreePicture(temp_src, 0); if (temp_mask != mask) FreePicture(temp_mask, 0); + return ret; } +void +glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height) +{ + _glamor_composite(op, source, mask, dest, x_source, y_source, + x_mask, y_mask, x_dest, y_dest, width, height, + TRUE); +} + +Bool +glamor_composite_nf(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height) +{ + return _glamor_composite(op, source, mask, dest, x_source, y_source, + x_mask, y_mask, x_dest, y_dest, width, height, + FALSE); +} + + + /** * Creates an appropriate picture to upload our alpha mask into (which @@ -1418,11 +1457,11 @@ glamor_create_mask_picture(ScreenPtr screen, * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid * accumulation in system memory. */ -void -glamor_trapezoids(CARD8 op, +static Bool +_glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps) + int ntrap, xTrapezoid * traps, Bool fallback) { ScreenPtr screen = dst->pDrawable->pScreen; BoxRec bounds; @@ -1446,13 +1485,13 @@ glamor_trapezoids(CARD8 op, for (; ntrap; ntrap--, traps++) glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, 1, traps); - return; + return TRUE; } miTrapezoidBounds(ntrap, traps, &bounds); if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; + return TRUE; x_dst = traps[0].left.p1.x >> 16; y_dst = traps[0].left.p1.y >> 16; @@ -1463,13 +1502,13 @@ glamor_trapezoids(CARD8 op, picture = glamor_create_mask_picture(screen, dst, mask_format, width, height); if (!picture) - return; + return TRUE; image = pixman_image_create_bits(picture->format, width, height, NULL, stride); if (!image) { FreePicture(picture, 0); - return; + return TRUE; } for (; ntrap; ntrap--, traps++) @@ -1497,8 +1536,31 @@ glamor_trapezoids(CARD8 op, pixman_image_unref(image); FreePicture(picture, 0); + return TRUE; } +void +glamor_trapezoids(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) +{ + _glamor_trapezoids(op, src, dst, mask_format, x_src, + y_src, ntrap, traps, TRUE); +} + +Bool +glamor_trapezoids_nf(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) +{ + return _glamor_trapezoids(op, src, dst, mask_format, x_src, + y_src, ntrap, traps, FALSE); +} + + + void glamor_composite_rects(CARD8 op, PicturePtr src, PicturePtr mask, PicturePtr dst, diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c index 3cbdd55a8..b7ddd823e 100644 --- a/glamor/glamor_triangles.c +++ b/glamor/glamor_triangles.c @@ -32,14 +32,15 @@ #include "glamor_priv.h" -void -glamor_triangles(CARD8 op, +static Bool +_glamor_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris) + INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris, Bool fallback) { - + if (!fallback) + return FALSE; if (glamor_prepare_access(pDst->pDrawable, GLAMOR_ACCESS_RW)) { if (pSrc->pDrawable == NULL || glamor_prepare_access(pSrc->pDrawable, @@ -53,4 +54,28 @@ glamor_triangles(CARD8 op, glamor_finish_access(pDst->pDrawable); } + return TRUE; } + +void +glamor_triangles(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris) +{ + _glamor_triangles(op, pSrc, pDst, maskFormat, + xSrc, ySrc, ntris, tris, TRUE); +} + +Bool +glamor_triangles_nf(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris) +{ + return _glamor_triangles(op, pSrc, pDst, maskFormat, + xSrc, ySrc, ntris, tris, FALSE); +} + From d135e879a6c8698bf21ae44a02315f370b961b14 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 9 Dec 2011 16:01:45 +0800 Subject: [PATCH 235/462] Can't create KHR image if the depth is uncompatible. Currently, KHR image only support one color format ARGB32. For all other format, we have to fail to create corresponding image and texture here. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index a068e39a6..ce8e6beff 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -108,7 +108,7 @@ glamor_egl_get_screen_private(ScrnInfoPtr scrn) static EGLImageKHR _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, - int width, int height, int stride, int name) + int width, int height, int stride, int name, int depth) { EGLImageKHR image; EGLint attribs[] = { @@ -126,7 +126,9 @@ _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, attribs[1] = width; attribs[3] = height; - attribs[5] = stride / 4; + attribs[5] = stride; + if (depth != 32) + return EGL_NO_IMAGE_KHR; image = glamor_egl->egl_create_image_khr(glamor_egl->display, glamor_egl->context, EGL_DRM_BUFFER_MESA, @@ -165,6 +167,7 @@ glamor_create_texture_from_image(struct glamor_egl_screen_private (glamor_egl->egl_image_target_texture2d_oes) (GL_TEXTURE_2D, image); + glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, 0); return TRUE; } @@ -193,8 +196,8 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) image = _glamor_egl_create_image(glamor_egl, scrn->virtualX, scrn->virtualY, - stride, - glamor_egl->front_buffer_handle); + stride / 4, + glamor_egl->front_buffer_handle, 32); if (image == EGL_NO_IMAGE_KHR) return FALSE; @@ -208,8 +211,6 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) /* * This function will be called from the dri buffer allocation. * It is somehow very familiar with the create textured screen. - * XXX the egl image here is not stored at any data structure. - * Does this cause a leak problem? */ Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) @@ -221,19 +222,20 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) EGLImageKHR image; GLuint texture; int name; + if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink pixmap handle\n"); return FALSE; } - image = _glamor_egl_create_image(glamor_egl, pixmap->drawable.width, - pixmap->drawable.height, stride, - name); + pixmap->drawable.height, + ((stride * 8 + 7) / pixmap->drawable.bitsPerPixel), + name, + pixmap->drawable.depth); if (image == EGL_NO_IMAGE_KHR) { - ErrorF("Failed to create khr image for bo handle %d.\n", handle); return FALSE; } From 92fd83872f5509a2792338b4665dc2b3e1ed68cd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 11 Dec 2011 02:26:15 +0800 Subject: [PATCH 236/462] Remove the access mode from private pixmap structure. Change the finish_access to pass in the access mode, and remove the access mode from the pixmap structure. This element should not be a pixmap's property. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 4 ++-- glamor/glamor_core.c | 19 ++++++++++--------- glamor/glamor_fill.c | 2 +- glamor/glamor_fillspans.c | 2 +- glamor/glamor_getspans.c | 2 +- glamor/glamor_picture.c | 4 ++-- glamor/glamor_polyfillrect.c | 2 +- glamor/glamor_polylines.c | 2 +- glamor/glamor_priv.h | 6 ++---- glamor/glamor_putimage.c | 4 ++-- glamor/glamor_render.c | 6 +++--- glamor/glamor_setspans.c | 2 +- glamor/glamor_triangles.c | 4 ++-- 13 files changed, 29 insertions(+), 30 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 38254d6fc..98da98a11 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -422,9 +422,9 @@ _glamor_copy_n_to_n(DrawablePtr src, dx, dy, reverse, upsidedown, bitplane, closure); if (dst != src) - glamor_finish_access(src); + glamor_finish_access(src, GLAMOR_ACCESS_RO); } - glamor_finish_access(dst); + glamor_finish_access(dst, GLAMOR_ACCESS_RW); } done: diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 4c58022a8..54e110a37 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -255,7 +255,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) } void -glamor_finish_access(DrawablePtr drawable) +glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = @@ -267,7 +267,7 @@ glamor_finish_access(DrawablePtr drawable) if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return; - if (pixmap_priv->access_mode != GLAMOR_ACCESS_RO) { + if (access_mode != GLAMOR_ACCESS_RO) { glamor_restore_pixmap_to_texture(pixmap); } @@ -307,7 +307,8 @@ glamor_prepare_access_gc(GCPtr gc) GLAMOR_ACCESS_RO)) { if (gc->stipple) glamor_finish_access(&gc-> - stipple->drawable); + stipple->drawable, + GLAMOR_ACCESS_RO); return FALSE; } } @@ -321,9 +322,9 @@ void glamor_finish_access_gc(GCPtr gc) { if (gc->fillStyle == FillTiled) - glamor_finish_access(&gc->tile.pixmap->drawable); + glamor_finish_access(&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RO); if (gc->stipple) - glamor_finish_access(&gc->stipple->drawable); + glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO); } Bool @@ -406,7 +407,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) (old_tile, drawable->bitsPerPixel); glamor_finish_access - (&old_tile->drawable); + (&old_tile->drawable, GLAMOR_ACCESS_RO); } } if (new_tile) { @@ -432,7 +433,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) GLAMOR_ACCESS_RW)) { fbPadPixmap(gc->tile.pixmap); glamor_finish_access - (&gc->tile.pixmap->drawable); + (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW); } } } @@ -449,7 +450,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) if (glamor_prepare_access (&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { fbValidateGC(gc, changes, drawable); - glamor_finish_access(&gc->stipple->drawable); + glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW); } } else { fbValidateGC(gc, changes, drawable); @@ -491,7 +492,7 @@ glamor_bitmap_to_region(PixmapPtr pixmap) if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) return NULL; ret = fbPixmapToRegion(pixmap); - glamor_finish_access(&pixmap->drawable); + glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); return ret; } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index b20ec5e39..10baeb3bf 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -88,7 +88,7 @@ glamor_fill(DrawablePtr drawable, fbFill(drawable, gc, x, y, width, height); glamor_finish_access_gc(gc); } - glamor_finish_access(drawable); + glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } return TRUE; } diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 996f0c5e8..bbe098571 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -83,7 +83,7 @@ _glamor_fill_spans(DrawablePtr drawable, sorted); glamor_finish_access_gc(gc); } - glamor_finish_access(drawable); + glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } return TRUE; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index dff55ba73..fc0d90b3e 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -101,7 +101,7 @@ glamor_get_spans(DrawablePtr drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { fbGetSpans(drawable, wmax, points, widths, count, dst); - glamor_finish_access(drawable); + glamor_finish_access(drawable, GLAMOR_ACCESS_RO); } } diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 68c90eb7a..3b5d56892 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -33,12 +33,12 @@ glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access) } void -glamor_finish_access_picture(PicturePtr picture) +glamor_finish_access_picture(PicturePtr picture, glamor_access_t access) { if (!picture || !picture->pDrawable) return; - glamor_finish_access(picture->pDrawable); + glamor_finish_access(picture->pDrawable, access); } /* diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 44df8a80f..8a691bbb2 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -102,7 +102,7 @@ _glamor_poly_fill_rect(DrawablePtr drawable, fbPolyFillRect(drawable, gc, nrect, prect); glamor_finish_access_gc(gc); } - glamor_finish_access(drawable); + glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } return TRUE; } diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 01124bbe0..2bb36c7e6 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -151,7 +151,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, fbPolyLine(temp_dest, gc, mode, n, points); glamor_finish_access_gc(gc); } - glamor_finish_access(temp_dest); + glamor_finish_access(temp_dest, GLAMOR_ACCESS_RW); } } else { /* fb calls mi functions in the lineWidth != 0 case. */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 4dfdbc456..1a462e200 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -226,7 +226,6 @@ typedef union _glamor_pending_op { * @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. * #pending_op: currently only support pending filling. * @container: The corresponding pixmap's pointer. @@ -240,7 +239,6 @@ typedef struct glamor_pixmap_private { GLuint tex; GLuint fb; GLuint pbo; - glamor_access_t access_mode; PictFormatShort pict_format; glamor_pending_op pending_op; PixmapPtr container; @@ -316,7 +314,7 @@ void glamor_copy_window(WindowPtr win, DDXPointRec old_origin, /* glamor_core.c */ Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access); -void glamor_finish_access(DrawablePtr drawable); +void glamor_finish_access(DrawablePtr drawable, glamor_access_t access); Bool glamor_prepare_access_window(WindowPtr window); void glamor_finish_access_window(WindowPtr window); Bool glamor_prepare_access_gc(GCPtr gc); @@ -524,7 +522,7 @@ 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_finish_access_picture(PicturePtr picture, glamor_access_t access); void glamor_destroy_picture(PicturePtr picture); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 989f635da..61018500d 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -234,7 +234,7 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); - glamor_finish_access(drawable); + glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } } #endif @@ -401,7 +401,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { fbPutImage(&pixmap->drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); - glamor_finish_access(&pixmap->drawable); + glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RW); } return TRUE; } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e7e53053c..fa4253283 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1366,11 +1366,11 @@ _glamor_composite(CARD8 op, x_mask, y_mask, x_dest, y_dest, width, height); if (mask) - glamor_finish_access_picture(mask); + glamor_finish_access_picture(mask, GLAMOR_ACCESS_RO); } - glamor_finish_access_picture(source); + glamor_finish_access_picture(source, GLAMOR_ACCESS_RO); } - glamor_finish_access_picture(dest); + glamor_finish_access_picture(dest, GLAMOR_ACCESS_RW); } done: if (temp_src != source) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 61163ce9b..4d6fe9602 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -101,6 +101,6 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbSetSpans(drawable, gc, src, points, widths, n, sorted); - glamor_finish_access(drawable); + glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } } diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c index b7ddd823e..1ea7fd665 100644 --- a/glamor/glamor_triangles.c +++ b/glamor/glamor_triangles.c @@ -50,9 +50,9 @@ _glamor_triangles(CARD8 op, ySrc, ntris, tris); } if (pSrc->pDrawable != NULL) - glamor_finish_access(pSrc->pDrawable); + glamor_finish_access(pSrc->pDrawable, GLAMOR_ACCESS_RO); - glamor_finish_access(pDst->pDrawable); + glamor_finish_access(pDst->pDrawable, GLAMOR_ACCESS_RW); } return TRUE; } From 10ad332dedad2df13212dcd198d947a2f5c76862 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 11 Dec 2011 08:06:13 +0800 Subject: [PATCH 237/462] Remove garbage file. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.indent.c | 821 ---------------------------------- 1 file changed, 821 deletions(-) delete mode 100644 glamor/glamor_pixmap.indent.c diff --git a/glamor/glamor_pixmap.indent.c b/glamor/glamor_pixmap.indent.c deleted file mode 100644 index f02acc746..000000000 --- a/glamor/glamor_pixmap.indent.c +++ /dev/null @@ -1,821 +0,0 @@ -#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; -} - - -static void -_glamor_pixmap_validate_filling(glamor_screen_private * glamor_priv, - glamor_pixmap_private * pixmap_priv) -{ - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - GLfloat vertices[8]; - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(glamor_priv->solid_prog); - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, - 1, pixmap_priv->pending_op.fill.color4fv); - vertices[0] = -1; - vertices[1] = -1; - vertices[2] = 1; - vertices[3] = -1; - vertices[4] = 1; - vertices[5] = 1; - vertices[6] = -1; - vertices[7] = 1; - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); - pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; -} - - -glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { - NULL, - _glamor_pixmap_validate_filling -}; - -void -glamor_pixmap_init(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; -} - -void -glamor_validate_pixmap(PixmapPtr pixmap) -{ - glamor_pixmap_validate_function_t validate_op; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - - validate_op = - glamor_priv->pixmap_validate_funcs[pixmap_priv-> - pending_op.type]; - if (validate_op) { - (*validate_op) (glamor_priv, pixmap_priv); - } -} - -void -glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) -{ - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); -#ifndef GLAMOR_GLES2 - dispatch->glMatrixMode(GL_PROJECTION); - dispatch->glLoadIdentity(); - dispatch->glMatrixMode(GL_MODELVIEW); - dispatch->glLoadIdentity(); -#endif - dispatch->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) -{ - int err; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - - err = glamor_set_destination_pixmap_priv(pixmap_priv); - return err; -} - -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(struct glamor_gl_dispatch *dispatch, unsigned char alu) -{ -#ifndef GLAMOR_GLES2 - if (alu == GXcopy) { - dispatch->glDisable(GL_COLOR_LOGIC_OP); - return; - } - dispatch->glEnable(GL_COLOR_LOGIC_OP); - switch (alu) { - case GXclear: - dispatch->glLogicOp(GL_CLEAR); - break; - case GXand: - dispatch->glLogicOp(GL_AND); - break; - case GXandReverse: - dispatch->glLogicOp(GL_AND_REVERSE); - break; - case GXandInverted: - dispatch->glLogicOp(GL_AND_INVERTED); - break; - case GXnoop: - dispatch->glLogicOp(GL_NOOP); - break; - case GXxor: - dispatch->glLogicOp(GL_XOR); - break; - case GXor: - dispatch->glLogicOp(GL_OR); - break; - case GXnor: - dispatch->glLogicOp(GL_NOR); - break; - case GXequiv: - dispatch->glLogicOp(GL_EQUIV); - break; - case GXinvert: - dispatch->glLogicOp(GL_INVERT); - break; - case GXorReverse: - dispatch->glLogicOp(GL_OR_REVERSE); - break; - case GXcopyInverted: - dispatch->glLogicOp(GL_COPY_INVERTED); - break; - case GXorInverted: - dispatch->glLogicOp(GL_OR_INVERTED); - break; - case GXnand: - dispatch->glLogicOp(GL_NAND); - break; - case GXset: - dispatch->glLogicOp(GL_SET); - break; - default: - FatalError("unknown logic op\n"); - } -#else - if (alu != GXcopy) - ErrorF("unsupported alu %x \n", alu); -#endif -} - - - - -/** - * Upload pixmap to a specified texture. - * This texture may not be the one attached to it. - **/ -int in_restore = 0; -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); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - unsigned int stride, row_length; - void *texels; - GLenum iformat; - - switch (pixmap->drawable.depth) { -#if 0 - case 8: - iformat = GL_ALPHA; - break; -#endif - case 24: - iformat = GL_RGB; - break; - default: - iformat = GL_RGBA; - break; - } - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - iformat = format; - } - - stride = pixmap->devKind; - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - } else { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } - - if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { - texels = NULL; - dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, - pixmap_priv->pbo); - } else - texels = pixmap->devPrivate.ptr; - - dispatch->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 no_alpha, int no_revert, - int flip) -{ - - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - 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 (no_alpha == 0 && no_revert == 1 && !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. */ - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - ptexcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - dispatch->glGenTextures(1, &tex); - - __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); -#ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); -#endif - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - dispatch->glUniform1i(glamor_priv-> - finish_access_no_revert[no_alpha], - no_revert); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], - 0); - - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - -#ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); -#endif - dispatch->glUseProgram(0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glDeleteTextures(1, &tex); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -void -glamor_pixmap_ensure_fb(PixmapPtr pixmap) -{ - int status; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - - if (pixmap_priv->fb == 0) - dispatch->glGenFramebuffers(1, &pixmap_priv->fb); - assert(pixmap_priv->tex != 0); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); - dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, pixmap_priv->tex, - 0); - status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - const char *str; - switch (status) { - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - str = "incomplete attachment"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - str = "incomplete/missing attachment"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - str = "incomplete draw buffer"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - str = "incomplete read buffer"; - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - str = "unsupported"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - str = "incomplete multiple"; - break; - default: - str = "unknown error"; - break; - } - - LogMessageVerb(X_INFO, 0, - "destination is framebuffer incomplete: %s [%#x]\n", - str, status); - assert(0); - } -} - -/* - * Prepare to upload a pixmap to texture memory. - * no_alpha equals 1 means the format needs to wire alpha to 1. - * Two condtion need to setup a fbo for a pixmap - * 1. !yInverted, we need to do flip if we are not yInverted. - * 2. no_alpha != 0, we need to wire the alpha. - * */ -static int -glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) -{ - int need_fbo; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - - if (!glamor_check_fbo_size - (glamor_priv, 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 (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) - need_fbo = 1; - else - need_fbo = 0; - - if (pixmap_priv->tex == 0) - dispatch->glGenTextures(1, &pixmap_priv->tex); - - if (need_fbo) { - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - pixmap->drawable.width, - pixmap->drawable.height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL); - glamor_pixmap_ensure_fb(pixmap); - } - - return 0; -} - -enum glamor_pixmap_status -glamor_upload_pixmap_to_texture(PixmapPtr pixmap) -{ - GLenum format, type; - int no_alpha, no_revert; - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, &no_alpha, - &no_revert)) { - glamor_fallback("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - return GLAMOR_UPLOAD_FAILED; - } - if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) - 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, no_alpha, - no_revert, 1); - 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 no_alpha, no_revert; - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, &no_alpha, - &no_revert)) { - ErrorF("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - assert(0); - } - - in_restore = 1; - _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - no_revert, 1); - in_restore = 0; -} - -/* - * as gles2 only support a very small set of color format and - * type when do glReadPixel, - * Before we use glReadPixels to get back a textured pixmap, - * Use shader to convert it to a supported format and thus - * get a new temporary pixmap returned. - * */ - -PixmapPtr -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, - GLenum * type, int no_alpha, int no_revert) -{ - glamor_pixmap_private *source_priv; - glamor_screen_private *glamor_priv; - ScreenPtr screen; - PixmapPtr temp_pixmap; - glamor_pixmap_private *temp_pixmap_priv; - glamor_gl_dispatch *dispatch; - static float vertices[8] = { -1, -1, - 1, -1, - 1, 1, - -1, 1 - }; - static float texcoords[8] = { 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - int swap_rb = 0; - - screen = source->drawable.pScreen; - - glamor_priv = glamor_get_screen_private(screen); - source_priv = glamor_get_pixmap_private(source); - dispatch = &glamor_priv->dispatch; - if (*format == GL_BGRA) { - *format = GL_RGBA; - swap_rb = 1; - } - - - temp_pixmap = (*screen->CreatePixmap) (screen, - source->drawable.width, - source->drawable.height, - source->drawable.depth, 0); - - temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - - dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, - source->drawable.width, - source->drawable.height, 0, *format, *type, - NULL); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); - - glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); - - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); - dispatch->glUniform1i(glamor_priv-> - finish_access_no_revert[no_alpha], - no_revert); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], - swap_rb); - - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - return temp_pixmap; -} - - -/** - * 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 no_alpha, no_revert; - uint8_t *data = NULL, *read; - PixmapPtr temp_pixmap = NULL; - ScreenPtr screen; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - - screen = pixmap->drawable.pScreen; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return TRUE; - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, &no_alpha, - &no_revert)) { - ErrorF("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - assert(0); // Should never happen. - return FALSE; - } - - pixmap_priv->access_mode = access; - 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; - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - /* XXX we may don't need to validate it on GPU here, - * we can just validate it on CPU. */ - glamor_validate_pixmap(pixmap); - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && - ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) - || no_revert != 1)) { - - temp_pixmap = - glamor_es2_pixmap_read_prepare(pixmap, &format, - &type, no_alpha, - no_revert); - - } - switch (access) { - case GLAMOR_ACCESS_RO: - gl_access = GL_READ_ONLY; - gl_usage = GL_STREAM_READ; - break; - case GLAMOR_ACCESS_WO: - data = malloc(stride * pixmap->drawable.height); - goto done; - break; - case GLAMOR_ACCESS_RW: - gl_access = GL_READ_WRITE; - gl_usage = GL_DYNAMIC_DRAW; - break; - default: - ErrorF("Glamor: Invalid access code. %d\n", access); - assert(0); - } - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - data = malloc(stride * pixmap->drawable.height); - } - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); - } else { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); - // dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, 0); - } - if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { - - if (!glamor_priv->yInverted) { - assert(glamor_priv->gl_flavor == - GLAMOR_GL_DESKTOP); - dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); - } - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (pixmap_priv->pbo == 0) - dispatch->glGenBuffers(1, - &pixmap_priv->pbo); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->pbo); - dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, - stride * - pixmap->drawable.height, - NULL, gl_usage); - dispatch->glReadPixels(0, 0, row_length, - pixmap->drawable.height, - format, type, 0); - data = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, - gl_access); - pixmap_priv->pbo_valid = TRUE; - - if (!glamor_priv->yInverted) { - assert(glamor_priv->gl_flavor == - GLAMOR_GL_DESKTOP); - dispatch->glPixelStorei - (GL_PACK_INVERT_MESA, 0); - } - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - } else { - if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) - type = GL_UNSIGNED_SHORT_5_5_5_1; - dispatch->glReadPixels(0, 0, - pixmap->drawable.width, - pixmap->drawable.height, - format, type, data); - } - } else { - data = malloc(stride * pixmap->drawable.height); - assert(data); - if (access != GLAMOR_ACCESS_WO) { - if (pixmap_priv->pbo == 0) - dispatch->glGenBuffers(1, - &pixmap_priv->pbo); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->pbo); - dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, - stride * - pixmap->drawable.height, - NULL, GL_STREAM_READ); - dispatch->glReadPixels(0, 0, row_length, - pixmap->drawable.height, - format, type, 0); - read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, - GL_READ_ONLY); - - for (y = 0; y < pixmap->drawable.height; y++) - memcpy(data + y * stride, - read + (pixmap->drawable.height - - y - 1) * stride, stride); - dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; - } - } - - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); - done: - pixmap->devPrivate.ptr = data; - - if (temp_pixmap) { - (*screen->DestroyPixmap) (temp_pixmap); - } - - return TRUE; -} - - - -static void -_glamor_destroy_upload_pixmap(PixmapPtr pixmap) -{ - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - - assert(pixmap_priv->gl_fbo == 0); - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; - -} - -void -glamor_destroy_upload_pixmap(PixmapPtr pixmap) -{ - _glamor_destroy_upload_pixmap(pixmap); -} From 36d424feaeec765d131c015df77d24db1a36fc38 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 12 Dec 2011 06:56:36 +0800 Subject: [PATCH 238/462] Call glamor_create_pixmap directly in glamor rendering path. When glamor is rendering pixmaps, and needs to create some temporary pixmap, it's better to use glamor version create pixmap directly. As if goes to external DDX's create pixmap, it may create a external DRM buffer which is not necessary. All the case within glamor scope is to create a texture only pixmap or a in memory pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 11 ++++------- glamor/glamor_copyarea.c | 19 +++++++++---------- glamor/glamor_getspans.c | 2 +- glamor/glamor_glyphs.c | 18 +++++++++--------- glamor/glamor_pixmap.c | 14 ++++++-------- glamor/glamor_polylines.c | 10 +++++----- glamor/glamor_priv.h | 5 +++++ glamor/glamor_render.c | 4 ++-- 8 files changed, 41 insertions(+), 42 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 482a07416..c1718bf1b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -114,14 +114,10 @@ glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, glamor_priv->screen_fbo = pixmap_priv->fb; } - - #define GLAMOR_PIXMAP_MEMORY 0 #define GLAMOR_PIXMAP_TEXTURE 1 - - -static PixmapPtr +PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { @@ -163,8 +159,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; - if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) + if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) { return pixmap; + } switch (depth) { #if 0 @@ -218,7 +215,7 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap) } } -static Bool +Bool glamor_destroy_pixmap(PixmapPtr pixmap) { glamor_destroy_textured_pixmap(pixmap); diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 98da98a11..625647d63 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -360,13 +360,13 @@ _glamor_copy_n_to_n(DrawablePtr src, src_pixmap->drawable.width * src_pixmap->drawable.height))) { - temp_pixmap = (*screen->CreatePixmap) (screen, - bound.x2 - bound.x1, - bound.y2 - bound.y1, - src_pixmap-> - drawable.depth, - overlaped ? 0 : - GLAMOR_CREATE_PIXMAP_CPU); + temp_pixmap = glamor_create_pixmap(screen, + bound.x2 - bound.x1, + bound.y2 - bound.y1, + src_pixmap-> + drawable.depth, + overlaped ? 0 : + GLAMOR_CREATE_PIXMAP_CPU); if (!temp_pixmap) goto fail; glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); @@ -430,9 +430,8 @@ _glamor_copy_n_to_n(DrawablePtr src, done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); - if (temp_src != src) { - (*screen->DestroyPixmap) (temp_pixmap); - } + if (temp_src != src) + glamor_destroy_pixmap(temp_pixmap); return ret; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index fc0d90b3e..1fa4b4ca8 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -93,7 +93,7 @@ glamor_get_spans(DrawablePtr drawable, PixmapBytePad(widths[i], drawable->depth); } if (temp_pixmap) - pixmap->drawable.pScreen->DestroyPixmap(temp_pixmap); + glamor_destroy_pixmap(temp_pixmap); return; fail: diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 96e4c57ec..30d9e585b 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -172,10 +172,10 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) goto bail; /* Now allocate the pixmap and picture */ - pixmap = pScreen->CreatePixmap(pScreen, - CACHE_PICTURE_SIZE, - CACHE_PICTURE_SIZE, depth, - 0); + pixmap = glamor_create_pixmap(pScreen, + CACHE_PICTURE_SIZE, + CACHE_PICTURE_SIZE, depth, + 0); if (!pixmap) goto bail; @@ -184,7 +184,7 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) CPComponentAlpha, &component_alpha, serverClient, &error); - pScreen->DestroyPixmap(pixmap); + glamor_destroy_pixmap(pixmap); if (!picture) goto bail; @@ -244,7 +244,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, y); if (scratch != pGlyphPixmap) - screen->DestroyPixmap(scratch); + glamor_destroy_pixmap(scratch); FreeScratchGC(gc); } @@ -628,7 +628,7 @@ glamor_glyphs_via_mask(CARD8 op, mask_format = a8Format; } - mask_pixmap = screen->CreatePixmap(screen, width, height, + mask_pixmap = glamor_create_pixmap(screen, width, height, mask_format->depth, CREATE_PIXMAP_USAGE_SCRATCH); if (!mask_pixmap) @@ -638,7 +638,7 @@ glamor_glyphs_via_mask(CARD8 op, mask_format, CPComponentAlpha, &component_alpha, serverClient, &error); if (!mask) { - screen->DestroyPixmap(mask_pixmap); + glamor_destroy_pixmap(mask_pixmap); return; } gc = GetScratchGC(mask_pixmap->drawable.depth, screen); @@ -695,7 +695,7 @@ glamor_glyphs_via_mask(CARD8 op, x_src + x - x_dst, y_src + y - y_dst, 0, 0, x, y, width, height); FreePicture(mask, 0); - screen->DestroyPixmap(mask_pixmap); + glamor_destroy_pixmap(mask_pixmap); } static void diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 6f44aabd3..9559d1731 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -576,10 +576,10 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, } - temp_pixmap = (*screen->CreatePixmap) (screen, - source->drawable.width, - source->drawable.height, - source->drawable.depth, 0); + temp_pixmap = glamor_create_pixmap (screen, + source->drawable.width, + source->drawable.height, + source->drawable.depth, 0); temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); @@ -658,7 +658,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) return FALSE; } - pixmap_priv->access_mode = access; glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DOWNLOAD, "Downloading pixmap %p %dx%d depth%d\n", pixmap, @@ -789,9 +788,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) done: pixmap->devPrivate.ptr = data; - if (temp_pixmap) { - (*screen->DestroyPixmap) (temp_pixmap); - } + if (temp_pixmap) + glamor_destroy_pixmap(temp_pixmap); return TRUE; } diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 2bb36c7e6..62401f5c3 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -122,10 +122,10 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, y_max = points[i].y; } - temp_pixmap = drawable->pScreen->CreatePixmap(drawable->pScreen, - x_max - x_min + 1, - y_max - y_min + 1, - drawable->depth, 0); + temp_pixmap = glamor_create_pixmap(drawable->pScreen, + x_max - x_min + 1, + y_max - y_min + 1, + drawable->depth, 0); if (temp_pixmap) { temp_dest = &temp_pixmap->drawable; temp_gc = @@ -164,7 +164,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, 0, 0, x_max - x_min + 1, y_max - y_min + 1, x_min, y_min); - drawable->pScreen->DestroyPixmap(temp_pixmap); + glamor_destroy_pixmap(temp_pixmap); for (i = 0; i < n; i++) { points[i].x += x_min; points[i].y += y_min; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1a462e200..8d4181e69 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -231,6 +231,7 @@ typedef union _glamor_pending_op { * @container: The corresponding pixmap's pointer. **/ + typedef struct glamor_pixmap_private { unsigned char gl_fbo:1; unsigned char gl_tex:1; @@ -298,6 +299,10 @@ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); Bool glamor_close_screen(int idx, ScreenPtr screen); +PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, + unsigned int usage); + +Bool glamor_destroy_pixmap(PixmapPtr pixmap); /* glamor_copyarea.c */ RegionPtr diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index fa4253283..f522fd661 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1161,7 +1161,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, else format = source->format; - pixmap = screen->CreatePixmap(screen, + pixmap = glamor_create_pixmap(screen, width, height, PIXMAN_FORMAT_DEPTH(format), @@ -1442,7 +1442,7 @@ glamor_create_mask_picture(ScreenPtr screen, return 0; } - pixmap = screen->CreatePixmap(screen, 0, 0, + pixmap = glamor_create_pixmap(screen, 0, 0, pict_format->depth, GLAMOR_CREATE_PIXMAP_CPU); if (!pixmap) From e3d16c9ebdffe8e5793ee253cf9f72b884b42805 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 12 Dec 2011 07:09:03 +0800 Subject: [PATCH 239/462] Classfy glamor pixmap to different types. During the integration with intel driver, we introduce two new type of pixmap, one is TEXTURE_DRM, the other is DRM_ONLY. TEXTURE_DRM means we create a texture bind to the DRM buffer successfully. And then the texture and the external BO is consistent. DRM_ONLY means that we failed to create a texture from the external DRM BO. We need to handle those different types carefully, so we have to track them in the data structure. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 31 ++++++++++++++++++++++++------- glamor/glamor.h | 20 ++++++++++++++++++-- glamor/glamor_egl.c | 17 ++++++++++------- glamor/glamor_priv.h | 1 + 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index c1718bf1b..41afd33cf 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -60,6 +60,25 @@ glamor_get_drawable_pixmap(DrawablePtr drawable) return (PixmapPtr) drawable; } +_X_EXPORT void +glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) +{ + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL) { + pixmap_priv = calloc(sizeof(*pixmap_priv), 1); + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, pixmap_priv); + pixmap_priv->container = pixmap; + pixmap_priv->glamor_priv = glamor_priv; + } + pixmap_priv->type = type; +} + + _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) { @@ -114,9 +133,6 @@ glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, glamor_priv->screen_fbo = pixmap_priv->fb; } -#define GLAMOR_PIXMAP_MEMORY 0 -#define GLAMOR_PIXMAP_TEXTURE 1 - PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) @@ -124,7 +140,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, PixmapPtr pixmap; GLenum format; GLuint tex; - int type = GLAMOR_PIXMAP_TEXTURE; + glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -137,7 +153,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. If we exceed such limitation, we have to use framebuffer. */ - type = GLAMOR_PIXMAP_MEMORY; + type = GLAMOR_MEMORY; pixmap = fbCreatePixmap(screen, w, h, depth, usage); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, (((w * @@ -159,9 +175,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; - if (w == 0 || h == 0 || type == GLAMOR_PIXMAP_MEMORY) { + pixmap_priv->type = type; + if (w == 0 || h == 0 || type == GLAMOR_MEMORY) return pixmap; - } switch (depth) { #if 0 @@ -188,6 +204,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, GL_UNSIGNED_BYTE, NULL); glamor_set_pixmap_texture(pixmap, w, h, tex); + return pixmap; } diff --git a/glamor/glamor.h b/glamor/glamor.h index fd056e96a..6febb5933 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -50,6 +50,20 @@ | GLAMOR_USE_SCREEN \ | GLAMOR_USE_PICTURE_SCREEN) +/* + * glamor_pixmap_type : glamor pixmap's type. + * @MEMORY: pixmap is in memory. + * @TEXTURE_DRM: pixmap is in a texture created from a DRM buffer. + * @DRM_ONLY: pixmap is in a external DRM buffer. + * @TEXTURE_ONLY: pixmap is in an internal texture. + */ +typedef enum glamor_pixmap_type { + GLAMOR_MEMORY, + GLAMOR_TEXTURE_DRM, + GLAMOR_DRM_ONLY, + GLAMOR_TEXTURE_ONLY +} glamor_pixmap_type_t; + #define GLAMOR_EGL_EXTERNAL_BUFFER 3 extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); @@ -58,9 +72,11 @@ extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); extern _X_EXPORT Bool glamor_glyphs_init(ScreenPtr pScreen); -void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, - unsigned int tex); +extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, + unsigned int tex); + +extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type); extern _X_EXPORT void glamor_destroy_textured_pixmap(PixmapPtr pixmap); extern _X_EXPORT void glamor_block_handler(ScreenPtr screen); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index ce8e6beff..b66d35862 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -30,7 +30,8 @@ #ifdef HAVE_DIX_CONFIG_H #include #endif -#include +#define GLAMOR_FOR_XORG +#include "xorg-server.h" #include #include #include @@ -54,15 +55,13 @@ #include #include -#define GLAMOR_FOR_XORG - -#include -#include "glamor_gl_dispatch.h" - #define GLAMOR_VERSION_MAJOR 0 #define GLAMOR_VERSION_MINOR 1 #define GLAMOR_VERSION_PATCH 0 +#include "glamor.h" +#include "glamor_gl_dispatch.h" + static const char glamor_name[] = "glamor"; static DevPrivateKeyRec glamor_egl_pixmap_private_key_index; @@ -127,7 +126,7 @@ _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, attribs[1] = width; attribs[3] = height; attribs[5] = stride; - if (depth != 32) + if (depth != 32 && depth != 24) return EGL_NO_IMAGE_KHR; image = glamor_egl->egl_create_image_khr(glamor_egl->display, glamor_egl->context, @@ -226,6 +225,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink pixmap handle\n"); + glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); return FALSE; } @@ -236,12 +236,15 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) name, pixmap->drawable.depth); if (image == EGL_NO_IMAGE_KHR) { + glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); return FALSE; } glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, pixmap->drawable.height, texture); + + glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); return TRUE; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 8d4181e69..423e2fca6 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -233,6 +233,7 @@ typedef union _glamor_pending_op { typedef struct glamor_pixmap_private { + glamor_pixmap_type_t type; unsigned char gl_fbo:1; unsigned char gl_tex:1; unsigned char pbo_valid:1; From 47e86eea563601c4e1e356f7267b935fcdd542f7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 12 Dec 2011 09:48:04 +0800 Subject: [PATCH 240/462] Fallback if the pixmap is drm only. Glamor can't do anything with a drm only pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f522fd661..f219c29ac 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -517,7 +517,6 @@ glamor_composite_with_copy(CARD8 op, 0, 0, x_dest, y_dest, width, height)) return TRUE; ret = TRUE; - ErrorF("width %d height %d \n", width, height); if (!glamor_copy_n_to_n_nf(source->pDrawable, dest->pDrawable, NULL, REGION_RECTS(®ion), @@ -946,6 +945,7 @@ glamor_composite_with_shader(CARD8 op, 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"); @@ -1230,13 +1230,15 @@ _glamor_composite(CARD8 op, glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (!source_pixmap_priv) goto fail; + if (!source_pixmap_priv || source_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (!mask_pixmap_priv) goto fail; + if (!mask_pixmap_priv || mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; } if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) From 2d0ea392ec574efb96ac7a04ee72ba580417ba1e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 12 Dec 2011 09:49:06 +0800 Subject: [PATCH 241/462] Call screen's method to create pixmap. As we may need to fallback to DDX's rendering path during the glyphs, we have to call screen's create pixmap method to create pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 30d9e585b..d61d74b5f 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -172,7 +172,7 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) goto bail; /* Now allocate the pixmap and picture */ - pixmap = glamor_create_pixmap(pScreen, + pixmap = pScreen->CreatePixmap(pScreen, CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, depth, 0); @@ -628,7 +628,7 @@ glamor_glyphs_via_mask(CARD8 op, mask_format = a8Format; } - mask_pixmap = glamor_create_pixmap(screen, width, height, + mask_pixmap = screen->CreatePixmap(screen, width, height, mask_format->depth, CREATE_PIXMAP_USAGE_SCRATCH); if (!mask_pixmap) From f7539d9bff0a65b9430dcae8745bf5d4409a9f04 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 12 Dec 2011 09:58:03 +0800 Subject: [PATCH 242/462] Enable texture dynamic uploading. --- glamor/glamor_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 423e2fca6..b96900846 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -549,7 +549,7 @@ glamor_picture_format_fixup(PicturePtr picture, * fallback the whole process to cpu. Most of the time, * this will increase performance obviously. */ -//#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD +#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD //#define GLAMOR_DELAYED_FILLING From 8c7fcefb965bfdaaf0576347da20155d0415caa5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 13 Dec 2011 22:48:34 +0800 Subject: [PATCH 243/462] glamor-for-ddx: Exports all rendering/drawing functions. This commit exports all the rest rendering/drawing functions to the DDX drivers. And introduce some new pixmap type. For a pixmap which has a separated texture, we never fallback it to the DDX layer. This commit also adds the following new functions: glamor_composite_rects, glamor_get_image_nf which are needed by UXA framework. Just a simple wrapper function of miXXX. Will consider to optimize them next few weeks. This commit also Fixed a glyphs rendering bug pointed by Chris. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 10 +++--- glamor/glamor.c | 5 ++- glamor/glamor.h | 48 +++++++++++++++++++++++++ glamor/glamor_addtraps.c | 69 +++++++++++++++++++++++++++++++++++ glamor/glamor_copyarea.c | 14 +++++--- glamor/glamor_egl.c | 57 +++++++++++++++++++---------- glamor/glamor_fill.c | 7 +++- glamor/glamor_fillspans.c | 5 ++- glamor/glamor_getimage.c | 59 ++++++++++++++++++++++++++++++ glamor/glamor_getspans.c | 38 ++++++++++++++++---- glamor/glamor_glyphs.c | 59 ++++++++++++++++++++++++++---- glamor/glamor_picture.c | 6 +++- glamor/glamor_polyfillrect.c | 7 +++- glamor/glamor_priv.h | 26 +++++++++++--- glamor/glamor_putimage.c | 6 +++- glamor/glamor_render.c | 70 +++++++++++++++++++++++++++++------- glamor/glamor_setspans.c | 30 +++++++++++++--- glamor/glamor_triangles.c | 21 ++++++----- glamor/glamor_utils.h | 31 ++++++++++++++-- 19 files changed, 488 insertions(+), 80 deletions(-) create mode 100644 glamor/glamor_addtraps.c create mode 100644 glamor/glamor_getimage.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index a382eb5ce..17a3e771f 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -34,11 +34,13 @@ libglamor_la_SOURCES = \ glamor_setspans.c \ glamor_render.c \ glamor_tile.c \ - glamor_triangles.c\ - glamor_pixmap.c\ - glamor_picture.c\ + glamor_triangles.c\ + glamor_addtraps.c\ + glamor_getimage.c\ + glamor_pixmap.c\ + glamor_picture.c\ glamor_window.c\ - glamor_gl_dispatch.c\ + glamor_gl_dispatch.c\ glamor.h sdk_HEADERS = glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 41afd33cf..369368336 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -374,7 +374,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) screen->GetSpans = glamor_get_spans; glamor_priv->saved_get_image = screen->GetImage; - screen->GetImage = miGetImage; + screen->GetImage = glamor_get_image; glamor_priv->saved_change_window_attributes = screen->ChangeWindowAttributes; @@ -402,6 +402,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_triangles = ps->Triangles; ps->Triangles = glamor_triangles; + glamor_priv->saved_addtraps = ps->AddTraps; + ps->AddTraps = glamor_add_traps; + glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph; ps->UnrealizeGlyph = glamor_glyph_unrealize; } diff --git a/glamor/glamor.h b/glamor/glamor.h index 6febb5933..eace12873 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -41,9 +41,30 @@ #endif /* GLAMOR_H */ +/* @GLAMOR_INVERTED_Y_AXIS: + * set 1 means the GL env's origin (0,0) is at top-left. + * EGL/DRM platform is an example need to set this bit. + * glx platform's origin is at bottom-left thus need to + * clear this bit.*/ #define GLAMOR_INVERTED_Y_AXIS 1 + +/* @GLAMOR_USE_SCREEN: + * If want to let glamor to do everything including the + * create/destroy pixmap and handle the gc ops. need to + * set this bit. Standalone glamor DDX driver need to set + * this bit. + * Otherwise, need to clear this bit, as the intel video + * driver with glamor enabled. + * */ #define GLAMOR_USE_SCREEN 2 +/* @GLAMOR_USE_PICTURE_SCREEN: + * If want to let glamor to do all the composition related + * things, need to set this bit. Just as standalone glamor + * DDX driver. + * Otherwise, need to clear this bit, as the intel video + * driver with glamor enabled. + */ #define GLAMOR_USE_PICTURE_SCREEN 4 #define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS \ @@ -54,12 +75,16 @@ * glamor_pixmap_type : glamor pixmap's type. * @MEMORY: pixmap is in memory. * @TEXTURE_DRM: pixmap is in a texture created from a DRM buffer. + * @SEPARATE_TEXTURE: The texture is created from a DRM buffer, but + * the format is incompatible, so this type of pixmap + * will never fallback to DDX layer. * @DRM_ONLY: pixmap is in a external DRM buffer. * @TEXTURE_ONLY: pixmap is in an internal texture. */ typedef enum glamor_pixmap_type { GLAMOR_MEMORY, GLAMOR_TEXTURE_DRM, + GLAMOR_SEPARATE_TEXTURE, GLAMOR_DRM_ONLY, GLAMOR_TEXTURE_ONLY } glamor_pixmap_type_t; @@ -96,6 +121,11 @@ extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); #endif +/* Glamor rendering/drawing functions with XXX_nf. + * nf means no fallback within glamor internal if possible. If glamor + * fail to accelerate the operation, glamor will return a false, and the + * caller need to implement fallback method. Return a true means the + * rendering request get done successfully. */ extern _X_EXPORT Bool glamor_fill_spans_nf(DrawablePtr drawable, GCPtr gc, int n, DDXPointPtr points, @@ -157,4 +187,22 @@ extern _X_EXPORT Bool glamor_triangles_nf(CARD8 op, extern _X_EXPORT void glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph); +extern _X_EXPORT Bool glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int n, int sorted); + +extern _X_EXPORT Bool glamor_get_spans_nf(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst); + +extern _X_EXPORT Bool glamor_composite_rects_nf (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +extern _X_EXPORT Bool glamor_get_image_nf(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +extern _X_EXPORT Bool glamor_add_traps_nf(PicturePtr pPicture, + INT16 x_off, + INT16 y_off, int ntrap, xTrap * traps); diff --git a/glamor/glamor_addtraps.c b/glamor/glamor_addtraps.c new file mode 100644 index 000000000..28775e561 --- /dev/null +++ b/glamor/glamor_addtraps.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +static Bool +_glamor_add_traps(PicturePtr pPicture, + INT16 x_off, + INT16 y_off, int ntrap, xTrap * traps, + Bool fallback) +{ + if (!fallback + && ( !pPicture->pDrawable + || glamor_ddx_fallback_check_pixmap(pPicture->pDrawable))) + return FALSE; + + if (glamor_prepare_access_picture(pPicture, GLAMOR_ACCESS_RW)) { + fbAddTraps(pPicture, x_off, y_off, ntrap, traps); + glamor_finish_access_picture(pPicture, GLAMOR_ACCESS_RW); + } + + return TRUE; +} + +void +glamor_add_traps(PicturePtr pPicture, + INT16 x_off, + INT16 y_off, int ntrap, xTrap * traps) +{ + _glamor_add_traps(pPicture, x_off, y_off, ntrap, traps, TRUE); +} + +Bool +glamor_add_traps_nf(PicturePtr pPicture, + INT16 x_off, + INT16 y_off, int ntrap, xTrap * traps) +{ + return _glamor_add_traps(pPicture, x_off, y_off, ntrap, traps, FALSE); +} + diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 625647d63..049979afd 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -317,15 +317,17 @@ _glamor_copy_n_to_n(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; - if (!dst_pixmap_priv || !src_pixmap_priv) - goto fail; - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + if (!dst_pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); goto fail; } + if (!src_pixmap_priv) { + glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + } + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, @@ -398,7 +400,9 @@ _glamor_copy_n_to_n(DrawablePtr src, fail: - if (!fallback) { + if (!fallback + && glamor_ddx_fallback_check_pixmap(src) + && glamor_ddx_fallback_check_pixmap(dst)) { ret = FALSE; goto done; } diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index b66d35862..a157000ec 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -65,8 +65,7 @@ static const char glamor_name[] = "glamor"; static DevPrivateKeyRec glamor_egl_pixmap_private_key_index; -DevPrivateKey glamor_egl_pixmap_private_key = - &glamor_egl_pixmap_private_key_index; +DevPrivateKey glamor_egl_pixmap_private_key = &glamor_egl_pixmap_private_key_index; static void glamor_identify(int flags) @@ -121,8 +120,6 @@ _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; - - attribs[1] = width; attribs[3] = height; attribs[5] = stride; @@ -221,14 +218,15 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) EGLImageKHR image; GLuint texture; int name; + int ret; + glamor_pixmap_type_t type; if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink pixmap handle\n"); - glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); - return FALSE; + glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); + exit(1); } - image = _glamor_egl_create_image(glamor_egl, pixmap->drawable.width, pixmap->drawable.height, @@ -236,18 +234,41 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) name, pixmap->drawable.depth); if (image == EGL_NO_IMAGE_KHR) { - glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); - return FALSE; + GLenum format; + /* we have to create separated texture here. The reason is, if + * a DRM-buffer-only pixmap exist, and given a texture only + * pixmap as a source, then we will don't know how to render it + * within glamor, and we even can't find a good way to fallback + * to DDX driver, as DDX driver don't understand a texture only + * pixmap. */ + type = GLAMOR_SEPARATE_TEXTURE; + if (pixmap->drawable.depth == 24) + format = GL_RGB; + else + format = GL_RGBA; + glamor_egl->dispatch->glGenTextures(1, &texture); + glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, texture); + glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + glamor_egl->dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, pixmap->drawable.width, + pixmap->drawable.height, 0, format, + GL_UNSIGNED_BYTE, NULL); + ret = FALSE; + } else { + type = GLAMOR_TEXTURE_DRM; + glamor_create_texture_from_image(glamor_egl, image, &texture); + ret = TRUE; } - glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_pixmap_type(pixmap, type); glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, pixmap->drawable.height, texture); - - glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); - return TRUE; + + return ret; } void @@ -261,7 +282,7 @@ glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) if (pixmap->refcnt == 1) { image = dixLookupPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key); - if (image != EGL_NO_IMAGE_KHR) + if (image != EGL_NO_IMAGE_KHR && image != NULL) eglDestroyImageKHR(glamor_egl->display, image); } glamor_destroy_textured_pixmap(pixmap); @@ -357,10 +378,10 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version); #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ - if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT)) { \ - ErrorF("EGL_" #EXT "required.\n"); \ - return FALSE; \ - } + if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT)) { \ + ErrorF("EGL_" #EXT "required.\n"); \ + return FALSE; \ + } GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 10baeb3bf..d36313ae3 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -82,7 +82,12 @@ glamor_fill(DrawablePtr drawable, return TRUE; fail: - if (!fallback) return FALSE; + if (!fallback) { + if (glamor_ddx_fallback_check_pixmap(&dst_pixmap->drawable) + && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + } + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { fbFill(drawable, gc, x, y, width, height); diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index bbe098571..94cb81e77 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -74,7 +74,10 @@ _glamor_fill_spans(DrawablePtr drawable, return TRUE; fail: - if (!fallback) return FALSE; + if (!fallback + && glamor_ddx_fallback_check_pixmap(drawable) + && glamor_ddx_fallback_check_gc(gc)) + return FALSE; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c new file mode 100644 index 000000000..7a9280b43 --- /dev/null +++ b/glamor/glamor_getimage.c @@ -0,0 +1,59 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + + +static Bool +_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d, + Bool fallback) +{ + miGetImage(pDrawable, x, y, w, h, format, planeMask, d); + return TRUE; +} + +void +glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d) +{ + _glamor_get_image(pDrawable, x, y, w, h, format, planeMask, d, TRUE); + return; +} + +Bool +glamor_get_image_nf(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d) +{ + return _glamor_get_image(pDrawable, x, y, w, + h, format, planeMask, d, FALSE); +} diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 1fa4b4ca8..4d4108da3 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -31,10 +31,11 @@ #include "glamor_priv.h" -void -glamor_get_spans(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst) +static Bool +_glamor_get_spans(DrawablePtr drawable, + int wmax, + DDXPointPtr points, int *widths, int count, char *dst, + Bool fallback) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; @@ -49,7 +50,7 @@ glamor_get_spans(DrawablePtr drawable, uint8_t *readpixels_dst = (uint8_t *) dst; int x_off, y_off; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); goto fail; } @@ -94,14 +95,39 @@ glamor_get_spans(DrawablePtr drawable, } if (temp_pixmap) glamor_destroy_pixmap(temp_pixmap); - return; + return TRUE; fail: + + if (!fallback + && glamor_ddx_fallback_check_pixmap(drawable)) + return FALSE; 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); glamor_finish_access(drawable, GLAMOR_ACCESS_RO); } + return TRUE; } +void +glamor_get_spans(DrawablePtr drawable, + int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + _glamor_get_spans(drawable, wmax, points, + widths, count, dst, TRUE); +} + +Bool +glamor_get_spans_nf(DrawablePtr drawable, + int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + return _glamor_get_spans(drawable, wmax, points, + widths, count, dst, FALSE); +} + + + diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index d61d74b5f..33e06f1d3 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -184,7 +184,7 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) CPComponentAlpha, &component_alpha, serverClient, &error); - glamor_destroy_pixmap(pixmap); + pScreen->DestroyPixmap(pixmap); if (!picture) goto bail; @@ -239,12 +239,57 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, ValidateGC(&pCachePixmap->drawable, gc); scratch = pGlyphPixmap; + if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) { + scratch = glamor_create_pixmap(screen, + glyph->info.width, + glyph->info.height, + pCachePixmap-> + drawable.depth, 0); + if (scratch) { + if (pGlyphPixmap->drawable.depth != + pCachePixmap->drawable.depth) { + PicturePtr picture; + int error; + + picture = + CreatePicture(0, + &scratch->drawable, + PictureMatchFormat + (screen, + pCachePixmap-> + drawable.depth, + cache->picture->format), + 0, NULL, serverClient, + &error); + if (picture) { + ValidatePicture(picture); + glamor_composite(PictOpSrc, + pGlyphPicture, + NULL, picture, + 0, 0, 0, 0, 0, + 0, + glyph->info.width, + glyph->info.height); + FreePicture(picture, 0); + } + } else { + glamor_copy_area(&pGlyphPixmap->drawable, + &scratch->drawable, + gc, 0, 0, + glyph->info.width, + glyph->info.height, 0, 0); + } + } else { + scratch = pGlyphPixmap; + } + } + (*gc->ops->CopyArea)(&scratch->drawable, &pCachePixmap->drawable, gc, 0, 0, glyph->info.width, glyph->info.height, x, y); if (scratch != pGlyphPixmap) - glamor_destroy_pixmap(scratch); + screen->DestroyPixmap(scratch); FreeScratchGC(gc); } @@ -581,8 +626,8 @@ static void glamor_glyphs_flush_mask(PicturePtr mask, glamor_glyph_buffer_t * buffer) { #ifdef RENDER - glamor_composite_rects(PictOpAdd, buffer->source, NULL, mask, - buffer->count, buffer->rects); + glamor_composite_glyph_rects(PictOpAdd, buffer->source, NULL, mask, + buffer->count, buffer->rects); #endif buffer->count = 0; buffer->source = NULL; @@ -638,7 +683,7 @@ glamor_glyphs_via_mask(CARD8 op, mask_format, CPComponentAlpha, &component_alpha, serverClient, &error); if (!mask) { - glamor_destroy_pixmap(mask_pixmap); + screen->DestroyPixmap(mask_pixmap); return; } gc = GetScratchGC(mask_pixmap->drawable.depth, screen); @@ -695,7 +740,7 @@ glamor_glyphs_via_mask(CARD8 op, x_src + x - x_dst, y_src + y - y_dst, 0, 0, x, y, width, height); FreePicture(mask, 0); - glamor_destroy_pixmap(mask_pixmap); + screen->DestroyPixmap(mask_pixmap); } static void @@ -714,7 +759,7 @@ glamor_glyphs_flush_dst(CARD8 op, rect->y_src = y_src + rect->y_dst - y_dst; } - glamor_composite_rects(op, src, buffer->source, dst, + glamor_composite_glyph_rects(op, src, buffer->source, dst, buffer->count, &buffer->rects[0]); buffer->count = 0; diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 3b5d56892..a021109b2 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -42,7 +42,7 @@ glamor_finish_access_picture(PicturePtr picture, glamor_access_t access) } /* - * We should already has drawable attached to it, if it has one. + * We should already have drawable attached to it, if it has one. * Then set the attached pixmap to is_picture format, and set * the pict format. * */ @@ -64,6 +64,10 @@ glamor_create_picture(PicturePtr picture) if (pixmap_priv) { pixmap_priv->is_picture = 1; pixmap_priv->pict_format = picture->format; + /* XXX Some formats are compatible between glamor and ddx driver*/ + if (pixmap_priv->type == GLAMOR_TEXTURE_DRM + /*&& pixmap_priv->pict_format != PICT_b8g8r8a8*/) + glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); } return glamor_priv->saved_create_picture(picture); } diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 8a691bbb2..32afd093b 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -94,7 +94,12 @@ _glamor_poly_fill_rect(DrawablePtr drawable, return TRUE; fail: - if (!fallback) return FALSE; + + if (!fallback + && glamor_ddx_fallback_check_pixmap(drawable) + && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + glamor_fallback(" to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b96900846..72d7867c3 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -147,6 +147,7 @@ typedef struct glamor_screen_private { CopyWindowProcPtr saved_copy_window; BitmapToRegionProcPtr saved_bitmap_to_region; TrianglesProcPtr saved_triangles; + AddTrapsProcPtr saved_addtraps; CreatePictureProcPtr saved_create_picture; DestroyPictureProcPtr saved_destroy_picture; UnrealizeGlyphProcPtr saved_unrealize_glyph; @@ -444,10 +445,16 @@ void glamor_trapezoids(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps); void glamor_init_composite_shaders(ScreenPtr screen); -void glamor_composite_rects(CARD8 op, - PicturePtr src, PicturePtr mask, - PicturePtr dst, int nrect, - glamor_composite_rect_t * rects); +void glamor_composite_glyph_rects(CARD8 op, + PicturePtr src, PicturePtr mask, + PicturePtr dst, int nrect, + glamor_composite_rect_t * rects); +void glamor_composite_rects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + /* glamor_tile.c */ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, @@ -536,10 +543,19 @@ enum glamor_pixmap_status glamor_upload_picture_to_texture(PicturePtr picture); void - glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private * pixmap_priv); +void +glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + + +void +glamor_add_traps(PicturePtr pPicture, + INT16 x_off, + INT16 y_off, int ntrap, xTrap * traps); + #include"glamor_utils.h" /* Dynamic pixmap upload to texture if needed. diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 61018500d..f69e7195f 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -395,7 +395,11 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, fail: glamor_set_planemask(pixmap, ~0); - if (!fallback) return FALSE; + + if (!fallback + && glamor_ddx_fallback_check_pixmap(&pixmap->drawable)) + return FALSE; + glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index f219c29ac..4a2a4388a 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1155,7 +1155,6 @@ glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr dst; int error; PictFormatShort format; - if (!source->pDrawable) format = PICT_a8r8g8b8; else @@ -1176,7 +1175,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, PIXMAN_FORMAT_DEPTH(format), format), 0, 0, serverClient, &error); - screen->DestroyPixmap(pixmap); + glamor_destroy_pixmap(pixmap); if (!dst) return NULL; @@ -1226,18 +1225,24 @@ _glamor_composite(CARD8 op, } if (source->pDrawable) { - source_pixmap = - glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = - glamor_get_pixmap_private(source_pixmap); - if (!source_pixmap_priv || source_pixmap_priv->type == GLAMOR_DRM_ONLY) + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (!source_pixmap_priv) { + glamor_set_pixmap_type(source_pixmap, GLAMOR_MEMORY); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + } + if (source_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (!mask_pixmap_priv || mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (!mask_pixmap_priv) { + glamor_set_pixmap_type(mask_pixmap, GLAMOR_MEMORY); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + } + if (mask_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } if ((!source->pDrawable @@ -1336,10 +1341,17 @@ _glamor_composite(CARD8 op, dispatch->glUseProgram(0); dispatch->glDisable(GL_BLEND); - if (!fallback) { + if (!fallback + && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable) + && (!source_pixmap + || glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable)) + && (!mask_pixmap + || glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) { ret = FALSE; goto done; } + +fallback: glamor_fallback ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", source, source->pDrawable, @@ -1564,9 +1576,9 @@ glamor_trapezoids_nf(CARD8 op, void -glamor_composite_rects(CARD8 op, - PicturePtr src, PicturePtr mask, PicturePtr dst, - int nrect, glamor_composite_rect_t * rects) +glamor_composite_glyph_rects(CARD8 op, + PicturePtr src, PicturePtr mask, PicturePtr dst, + int nrect, glamor_composite_rect_t * rects) { int n; glamor_composite_rect_t *r; @@ -1592,4 +1604,38 @@ glamor_composite_rects(CARD8 op, } } +static Bool +_glamor_composite_rects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects, + Bool fallback) +{ + miCompositeRects(op, pDst, color, nRect, rects); + return TRUE; +} + +void +glamor_composite_rects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + _glamor_composite_rects(op, pDst, color, nRect, rects, TRUE); +} + +Bool +glamor_composite_rects_nf (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE); +} + + + #endif /* RENDER */ diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 4d6fe9602..360ca37af 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -31,9 +31,10 @@ #include "glamor_priv.h" -void -glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted) +static Bool +_glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int n, int sorted, + Bool fallback) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); glamor_screen_private *glamor_priv = @@ -94,13 +95,32 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(dispatch, GXcopy); dispatch->glDisable(GL_SCISSOR_TEST); - return; + return TRUE; fail: - + if (!fallback + && glamor_ddx_fallback_check_pixmap(drawable)) + return FALSE; 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); glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } + return TRUE; +} + +void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int n, int sorted) +{ + _glamor_set_spans(drawable, gc, src, points, + widths, n, sorted, TRUE); +} + +Bool +glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int n, int sorted) +{ + return _glamor_set_spans(drawable, gc, src, points, + widths, n, sorted, FALSE); } diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c index 1ea7fd665..208ac77f1 100644 --- a/glamor/glamor_triangles.c +++ b/glamor/glamor_triangles.c @@ -39,20 +39,23 @@ _glamor_triangles(CARD8 op, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris, Bool fallback) { - if (!fallback) + if (!fallback + && glamor_ddx_fallback_check_pixmap(pDst->pDrawable) + && (!pSrc->pDrawable + || glamor_ddx_fallback_check_pixmap(pSrc->pDrawable))) return FALSE; - if (glamor_prepare_access(pDst->pDrawable, GLAMOR_ACCESS_RW)) { - if (pSrc->pDrawable == NULL || - glamor_prepare_access(pSrc->pDrawable, - GLAMOR_ACCESS_RO)) { + + if (glamor_prepare_access_picture(pDst, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access_picture(pSrc, + GLAMOR_ACCESS_RO)) { fbTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris); - } - if (pSrc->pDrawable != NULL) - glamor_finish_access(pSrc->pDrawable, GLAMOR_ACCESS_RO); - glamor_finish_access(pDst->pDrawable, GLAMOR_ACCESS_RW); + glamor_finish_access_picture(pSrc, GLAMOR_ACCESS_RO); + } + + glamor_finish_access_picture(pDst, GLAMOR_ACCESS_RW); } return TRUE; } diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 265d9ed5c..4d47f57ae 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -541,9 +541,34 @@ glamor_get_rgba_from_pixel(CARD32 pixel, return TRUE; } +/* return TRUE if we can access this pixmap at DDX driver. */ +inline static Bool glamor_ddx_fallback_check_pixmap(DrawablePtr drawable) +{ + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + return (!pixmap_priv + || (pixmap_priv->type == GLAMOR_TEXTURE_DRM + || pixmap_priv->type == GLAMOR_MEMORY + || pixmap_priv->type == GLAMOR_DRM_ONLY)); +} - - - +inline static Bool glamor_ddx_fallback_check_gc(GCPtr gc) +{ + PixmapPtr pixmap; + if (!gc) + return TRUE; + switch (gc->fillStyle) { + case FillStippled: + case FillOpaqueStippled: + pixmap = gc->stipple; + break; + case FillTiled: + pixmap = gc->tile.pixmap; + break; + default: + pixmap = NULL; + } + return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable)); +} #endif From 3f5d53b33978bdb848dd605a19d3fb4ea5f259e0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 16 Dec 2011 15:02:54 +0800 Subject: [PATCH 244/462] Correct the logic of glamor_egl_create_textured_pixmap. Discussed with Chris and found the previous logic is not good. Now change it in this commit, this API will just try to create a textured pixmap from the handle provided by DDX driver, if failed simply return FALSE without touch the pixmap. And the DDX driver can choose how to do next step. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 58 ++++++++------------------------------------- 1 file changed, 10 insertions(+), 48 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index a157000ec..7cc52c860 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -204,10 +204,6 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) return TRUE; } -/* - * This function will be called from the dri buffer allocation. - * It is somehow very familiar with the create textured screen. - */ Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { @@ -218,8 +214,6 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) EGLImageKHR image; GLuint texture; int name; - int ret; - glamor_pixmap_type_t type; if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, @@ -233,42 +227,17 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) ((stride * 8 + 7) / pixmap->drawable.bitsPerPixel), name, pixmap->drawable.depth); - if (image == EGL_NO_IMAGE_KHR) { - GLenum format; - /* we have to create separated texture here. The reason is, if - * a DRM-buffer-only pixmap exist, and given a texture only - * pixmap as a source, then we will don't know how to render it - * within glamor, and we even can't find a good way to fallback - * to DDX driver, as DDX driver don't understand a texture only - * pixmap. */ - type = GLAMOR_SEPARATE_TEXTURE; - if (pixmap->drawable.depth == 24) - format = GL_RGB; - else - format = GL_RGBA; - glamor_egl->dispatch->glGenTextures(1, &texture); - glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, texture); - glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - glamor_egl->dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, pixmap->drawable.width, - pixmap->drawable.height, 0, format, - GL_UNSIGNED_BYTE, NULL); - ret = FALSE; - } else { - type = GLAMOR_TEXTURE_DRM; - glamor_create_texture_from_image(glamor_egl, image, &texture); - ret = TRUE; - } + if (image == EGL_NO_IMAGE_KHR) + return FALSE; - glamor_set_pixmap_type(pixmap, type); + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, pixmap->drawable.height, texture); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); - return ret; + return TRUE; } void @@ -327,7 +296,6 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, return FALSE; } - Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) { @@ -347,20 +315,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) xf86AllocateScrnInfoPrivateIndex(); scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; - glamor_egl->fd = fd; - - glamor_egl->display = eglGetDRMDisplayMESA(glamor_egl->fd); - - if (glamor_egl->display == EGL_NO_DISPLAY) { - glamor_egl->gbm = gbm_create_device(glamor_egl->fd); - if (glamor_egl->gbm == NULL) { - ErrorF("couldn't get display device\n"); - return FALSE; - } + glamor_egl->gbm = gbm_create_device(glamor_egl->fd); + if (glamor_egl->gbm == NULL) { + ErrorF("couldn't get display device\n"); + return FALSE; } - glamor_egl->display = eglGetDisplay(glamor_egl->gbm); + #ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); #else From 5769d8603ddef6a8023f12bba1d3d3cde83e82d4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 16 Dec 2011 15:04:33 +0800 Subject: [PATCH 245/462] Export glamor_create_texture to DDX driver. If DDX failed to create textured pixmap from its BO's handle, it can turn to call this API to create a brand new glamor rather than fallback to pure in memory pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index eace12873..4c01623d0 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -90,12 +90,29 @@ typedef enum glamor_pixmap_type { } glamor_pixmap_type_t; #define GLAMOR_EGL_EXTERNAL_BUFFER 3 - +/* @glamor_init: Initialize glamor internal data structure. + * + * @screen: Current screen pointer. + * @flags: Please refer the flags description above. + * + * This function initializes necessary internal data structure + * for glamor. And before calling into this function, the OpenGL + * environment should be ready. Should be called before any real + * glamor rendering or texture allocation functions. + */ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, int w, int h, unsigned int tex); +/* @glamor_glyphs_init: Initialize glyphs internal data structures. + * + * @pScreen: Current screen pointer. + * + * This function must be called after the glamor_init and the texture + * can be allocated. An example is to call it when create the screen + * resources at DDX layer. + */ extern _X_EXPORT Bool glamor_glyphs_init(ScreenPtr pScreen); extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, @@ -104,21 +121,65 @@ extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type); extern _X_EXPORT void glamor_destroy_textured_pixmap(PixmapPtr pixmap); extern _X_EXPORT void glamor_block_handler(ScreenPtr screen); +extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, + unsigned int usage); #ifdef GLAMOR_FOR_XORG +/* @glamor_egl_init: Initialize EGL environment. + * + * @scrn: Current screen info pointer. + * @fd: Current drm fd. + * + * This function creates and intialize EGL contexts. + * Should be called from DDX's preInit function. + * Return TRUE if success, otherwise return FALSE. + * */ extern _X_EXPORT Bool glamor_egl_init(ScrnInfoPtr scrn, int fd); + +/* @glamor_egl_init_textured_pixmap: Initialization for textured pixmap allocation. + * + * @screen: Current screen pointer. + * + * This function must be called before any textured pixmap's creation including + * the screen pixmap. Could be called from DDX's screenInit function after the calling + * to glamor_init.. + */ +extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); + +/* @glamor_egl_create_textured_screen: Create textured screen pixmap. + * + * @screen: screen pointer to be processed. + * @handle: screen pixmap's BO handle. + * @stride: screen pixmap's stride in bytes. + * + * This function is similar with the create_textured_pixmap. As the + * screen pixmap is a special, we handle it separately in this function. + */ extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride); + +/* + * @glamor_egl_create_textured_pixmap: Try to create a textured pixmap from + * a BO handle. + * + * @pixmap: The pixmap need to be processed. + * @handle: The BO's handle attached to this pixmap at DDX layer. + * @stride: Stride in bytes for this pixmap. + * + * This function try to create a texture from the handle and attach + * the texture to the pixmap , thus glamor can render to this pixmap + * as well. Return true if successful, otherwise return FALSE. + */ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride); +extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); + extern _X_EXPORT Bool glamor_egl_close_screen(ScreenPtr screen); extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); -extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); -extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); #endif /* Glamor rendering/drawing functions with XXX_nf. From 7285f2e836c56c31a42b8c18a7ebd0e8a7d78fa1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 16 Dec 2011 20:15:33 +0800 Subject: [PATCH 246/462] Make sure the devPrivate.ptr of a textured pixmap is NULL. Just in case when wrongly fallback to DDX layer and cause random memory corruption. Pointed out by Chris. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 369368336..630df4f58 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -116,6 +116,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) pixmap->drawable. bitsPerPixel + 7) / 8) + 3) & ~3, NULL); + pixmap->devPrivate.ptr = NULL; } /* Set screen pixmap. If tex equal to 0, means it is called from ephyr. */ From 2583620c6cd6a6fedeb7082b526f2751eb6f75b4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 23 Dec 2011 14:23:56 +0800 Subject: [PATCH 247/462] Remove useless egl functions. We only need to create image fron external name rather than use drm_image_mesa to create drm image, so remove them. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 7cc52c860..1450abbe9 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -87,8 +87,6 @@ struct glamor_egl_screen_private { int cpp; struct gbm_device *gbm; - PFNEGLCREATEDRMIMAGEMESA egl_create_drm_image_mesa; - PFNEGLEXPORTDRMIMAGEMESA egl_export_drm_image_mesa; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; struct glamor_gl_dispatch *dispatch; @@ -353,8 +351,6 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); #endif - glamor_egl->egl_export_drm_image_mesa = (PFNEGLEXPORTDRMIMAGEMESA) - eglGetProcAddress("eglExportDRMImageMESA"); glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); @@ -363,7 +359,6 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) eglGetProcAddress("glEGLImageTargetTexture2DOES"); if (!glamor_egl->egl_create_image_khr - || !glamor_egl->egl_export_drm_image_mesa || !glamor_egl->egl_image_target_texture2d_oes) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetProcAddress() failed\n"); From 3ba546b6998bf1c5d68ff0083017f804ffc48a93 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 23 Dec 2011 16:18:22 +0800 Subject: [PATCH 248/462] Code cleanup. Remove useless code, and after a fbCreatePixmap, we do not need to modify its header there. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 630df4f58..bbcf94258 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -156,17 +156,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, If we exceed such limitation, we have to use framebuffer. */ type = GLAMOR_MEMORY; pixmap = fbCreatePixmap(screen, w, h, depth, usage); - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, - (((w * - pixmap-> - drawable.bitsPerPixel + - 7) / 8) + 3) & ~3, NULL); -#if 0 - if (usage != GLAMOR_CREATE_PIXMAP_CPU) - glamor_fallback("choose cpu memory for pixmap %p ," - " %d x %d depth %d\n", pixmap, w, - h, depth); -#endif } else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); From b36d264ec98440707ed3a94fab430e23d4a1582a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 23 Dec 2011 16:19:39 +0800 Subject: [PATCH 249/462] Add a new API glamor_create_gc. As at ValidateGC stage, it may need to touch the pixmap directly, for example the tile pixmap. We must export this interface to DDX driver and let the DDX driver to route the processing to us. As this pixmap may be a texture only pixmap, and DDX don't know how to handle it. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor.h b/glamor/glamor.h index 4c01623d0..a15cdc40f 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -182,6 +182,7 @@ extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); #endif +extern _X_EXPORT int glamor_create_gc(GCPtr gc); /* Glamor rendering/drawing functions with XXX_nf. * nf means no fallback within glamor internal if possible. If glamor * fail to accelerate the operation, glamor will return a false, and the From f2809745fb641239be5b0281eac569c5b371e55e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 23 Dec 2011 16:21:44 +0800 Subject: [PATCH 250/462] Flush gl operations when destroy an textured image. Before destroy an image which was attached to a texture. we must call glFlush to make sure the operation on that texture has been done. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 1450abbe9..7eca5ad42 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -249,8 +249,13 @@ glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) if (pixmap->refcnt == 1) { image = dixLookupPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key); - if (image != EGL_NO_IMAGE_KHR && image != NULL) + if (image != EGL_NO_IMAGE_KHR && image != NULL) { + /* Before destroy an image which was attached to + * a texture. we must call glFlush to make sure the + * operation on that texture has been done.*/ + glamor_block_handler(pixmap->drawable.pScreen); eglDestroyImageKHR(glamor_egl->display, image); + } } glamor_destroy_textured_pixmap(pixmap); } From c65dc686228262894e0afc9fbe9fe6635d420e2f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 27 Dec 2011 16:42:32 +0800 Subject: [PATCH 251/462] Export glamor_validate_gc to DDX. This is also a function which may direct access pixmaps which may be a glamor only pixmap and DDX doesn't know how to access it. We have to export this API to DDX driver and let the DDX driver use it to do the validation. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 2 ++ glamor/glamor_core.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index a15cdc40f..fc8c152bc 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -183,6 +183,8 @@ extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); #endif extern _X_EXPORT int glamor_create_gc(GCPtr gc); + +extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable); /* Glamor rendering/drawing functions with XXX_nf. * nf means no fallback within glamor internal if possible. If glamor * fail to accelerate the operation, glamor will return a false, and the diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 54e110a37..9a1b770bd 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -366,7 +366,7 @@ GCOps glamor_gc_ops = { * uxa_validate_gc() sets the ops to glamor's implementations, which may be * accelerated or may sync the card and fall back to fb. */ -static void +void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) { /* fbValidateGC will do direct access to pixmaps if the tiling has changed. From 27c4c0457dac307500859ca7a14a1e58465d5e0b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 27 Dec 2011 16:44:17 +0800 Subject: [PATCH 252/462] Remove the assertion which is not safe sometimes. The original version assumes that each drawable pixmap should have a valid private pixmap pointer. But this is not true after we create this libglamor. As the DDX layer may create a pure software drawable pixmap which doesn't have a private pixmap pointer. Signed-off-by: Zhigang Gong --- glamor/glamor_picture.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index a021109b2..940c9d75a 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -16,9 +16,7 @@ glamor_upload_picture_to_texture(PicturePtr picture) 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); } @@ -65,8 +63,7 @@ glamor_create_picture(PicturePtr picture) pixmap_priv->is_picture = 1; pixmap_priv->pict_format = picture->format; /* XXX Some formats are compatible between glamor and ddx driver*/ - if (pixmap_priv->type == GLAMOR_TEXTURE_DRM - /*&& pixmap_priv->pict_format != PICT_b8g8r8a8*/) + if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); } return glamor_priv->saved_create_picture(picture); From 70b6341538cc11f074b02f9dd97d387418245d77 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 31 Dec 2011 19:14:06 +0800 Subject: [PATCH 253/462] Fixed a bug at putImage. fbPutImage wants the input drawable is the target drawable rather than the backing pixmap. This bug cause some XTS failures, now fix it. Signed-off-by: Zhigang Gong --- glamor/glamor_putimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index f69e7195f..7967e25a7 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -403,7 +403,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { - fbPutImage(&pixmap->drawable, gc, depth, x, y, w, h, + fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RW); } From fbccc4bbbc84a5459010d3238a00a0dd49111eec Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 31 Dec 2011 19:20:10 +0800 Subject: [PATCH 254/462] Fixed a rendering bug at fillspans. We should not change the points coords when loop for the clip rects. Change to use another variable to store the clipped coords and keep the original coords. This bug cause some XTS failures. Now fix it. Signed-off-by: Zhigang Gong --- glamor/glamor_fillspans.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 94cb81e77..97c4403ce 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -55,19 +55,19 @@ _glamor_fill_spans(DrawablePtr drawable, nbox = REGION_NUM_RECTS(pClip); pbox = REGION_RECTS(pClip); while (nbox--) { - if (pbox->y1 > y || pbox->y2 <= y) - continue; + int real_x1 = x1, real_x2 = x2; - if (x1 < pbox->x1) - x1 = pbox->x1; + if (real_x1 < pbox->x1) + real_x1 = pbox->x1; - if (x2 > pbox->x2) - x2 = pbox->x2; + if (real_x2 > pbox->x2) + real_x2 = pbox->x2; - if (x2 <= x1) - continue; - if (!glamor_fill(drawable, gc, x1, y, x2 - x1, 1, fallback)) - goto fail; + if (real_x2 > real_x1 && pbox->y1 <= y && pbox->y2 > y) { + if (!glamor_fill(drawable, gc, real_x1, y, + real_x2 - real_x1, 1, fallback)) + goto fail; + } pbox++; } } From d42eb04c29d015fb1e4ed4e9ded4c0dd8bc7dc3c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 31 Dec 2011 19:27:33 +0800 Subject: [PATCH 255/462] Remove useless output messages. Signed-off-by: Zhigang Gong --- glamor/glamor_tile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index bd5192c0a..f5a6e759f 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -117,7 +117,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) || ((tile_y != 0) && (tile_y + height > tile->drawable.height))) { - ErrorF("tile_x = %d tile_y = %d \n", tile_x, tile_y); goto fail; } if (glamor_priv->tile_prog == 0) { From 9264335347da641b2626a6b9f56aa05ab313239e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 31 Dec 2011 19:29:17 +0800 Subject: [PATCH 256/462] Added more drawing functions. As we want to take over all the possible GC ops from the DDX layer, we need to add all the missed functions. This commit also fixed one bug at polylines. We simply drop the bugy optimized code now, as it did not consider of clip info. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 3 + glamor/glamor.h | 27 +++++++ glamor/glamor_copyplane.c | 75 ++++++++++++++++++++ glamor/glamor_core.c | 12 ++-- glamor/glamor_glyphblt.c | 139 ++++++++++++++++++++++++++++++++++++ glamor/glamor_polylines.c | 92 ++++++++---------------- glamor/glamor_polyops.c | 143 ++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 32 ++++++++- 8 files changed, 452 insertions(+), 71 deletions(-) create mode 100644 glamor/glamor_copyplane.c create mode 100644 glamor/glamor_glyphblt.c create mode 100644 glamor/glamor_polyops.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 17a3e771f..5c5f7e5dc 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -37,6 +37,9 @@ libglamor_la_SOURCES = \ glamor_triangles.c\ glamor_addtraps.c\ glamor_getimage.c\ + glamor_copyplane.c\ + glamor_glyphblt.c\ + glamor_polyops.c\ glamor_pixmap.c\ glamor_picture.c\ glamor_window.c\ diff --git a/glamor/glamor.h b/glamor/glamor.h index fc8c152bc..1119e374b 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -270,3 +270,30 @@ extern _X_EXPORT Bool glamor_add_traps_nf(PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntrap, xTrap * traps); +extern _X_EXPORT Bool glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitPlane, RegionPtr *pRegion); + +extern _X_EXPORT Bool glamor_image_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase); + +extern _X_EXPORT Bool glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase); + +extern _X_EXPORT Bool glamor_push_pixels_nf(GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, int w, int h, int x, int y); + +extern _X_EXPORT Bool glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt); + +extern _X_EXPORT Bool glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg); + +extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt); + +extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points); + diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c new file mode 100644 index 000000000..288d7eddc --- /dev/null +++ b/glamor/glamor_copyplane.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +static Bool +_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitPlane, RegionPtr *pRegion, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_gc(pGC) + && glamor_ddx_fallback_check_pixmap(pSrc) + && glamor_ddx_fallback_check_pixmap(pDst)) + goto fail; + glamor_prepare_access(pDst, GLAMOR_ACCESS_RW); + glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO); + *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, bitPlane); + glamor_finish_access(pSrc, GLAMOR_ACCESS_RO); + glamor_finish_access(pDst, GLAMOR_ACCESS_RW); + return TRUE; + + fail: + return FALSE; +} + +RegionPtr +glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitPlane) +{ + RegionPtr ret; + _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, bitPlane, &ret, TRUE); + return ret; +} + +Bool +glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitPlane, RegionPtr *pRegion) +{ + return _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, bitPlane, pRegion, FALSE); +} diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 9a1b770bd..f865ece46 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -344,10 +344,10 @@ GCOps glamor_gc_ops = { .SetSpans = glamor_set_spans, .PutImage = glamor_put_image, .CopyArea = glamor_copy_area, - .CopyPlane = miCopyPlane, - .PolyPoint = miPolyPoint, + .CopyPlane = glamor_copy_plane, + .PolyPoint = glamor_poly_point, .Polylines = glamor_poly_lines, - .PolySegment = miPolySegment, + .PolySegment = glamor_poly_segment, .PolyRectangle = miPolyRectangle, .PolyArc = miPolyArc, .FillPolygon = miFillPolygon, @@ -357,9 +357,9 @@ GCOps glamor_gc_ops = { .PolyText16 = miPolyText16, .ImageText8 = miImageText8, .ImageText16 = miImageText16, - .ImageGlyphBlt = miImageGlyphBlt, - .PolyGlyphBlt = miPolyGlyphBlt, - .PushPixels = miPushPixels, + .ImageGlyphBlt = glamor_image_glyph_blt, //miImageGlyphBlt, + .PolyGlyphBlt = glamor_poly_glyph_blt, //miPolyGlyphBlt, + .PushPixels = glamor_push_pixels, //miPushPixels, }; /** diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c new file mode 100644 index 000000000..c9a35a0f1 --- /dev/null +++ b/glamor/glamor_glyphblt.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +static Bool +_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_pixmap(pDrawable) + && glamor_ddx_fallback_check_gc(pGC)) + goto fail; + glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); + glamor_prepare_access_gc(pGC); + fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + glamor_finish_access_gc(pGC); + glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + return TRUE; + fail: + return FALSE; +} + +void +glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + _glamor_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, TRUE); +} + +Bool +glamor_image_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + return _glamor_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, FALSE); +} + +static Bool +_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_pixmap(pDrawable) + && glamor_ddx_fallback_check_gc(pGC)) + goto fail; + glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); + glamor_prepare_access_gc(pGC); + fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + glamor_finish_access_gc(pGC); + glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + return TRUE; + fail: + return FALSE; +} + +void +glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, TRUE); +} + +Bool +glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + return _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase, FALSE); +} + +static Bool +_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, int w, int h, int x, int y, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_pixmap(pDrawable) + && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable) + && glamor_ddx_fallback_check_gc(pGC)) + goto fail; + glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); + glamor_prepare_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); + glamor_prepare_access_gc(pGC); + fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); + glamor_finish_access_gc(pGC); + glamor_finish_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); + glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + return TRUE; + fail: + return FALSE; +} + +void +glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, int w, int h, int x, int y) +{ + _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, TRUE); +} + +Bool +glamor_push_pixels_nf(GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, int w, int h, int x, int y) +{ + return _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, FALSE); +} + diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 62401f5c3..0217e8fcb 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -42,26 +42,19 @@ * horizontal or vertical lines (rectangles), and uses existing rectangle fill * acceleration if so. */ -void -glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, - DDXPointPtr points) +static Bool +_glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points, Bool fallback) { xRectangle *rects; int x1, x2, y1, y2; int i; - int x_min = MAXSHORT; - int x_max = MINSHORT; - int y_min = MAXSHORT; - int y_max = MINSHORT; - DrawablePtr temp_dest; - PixmapPtr temp_pixmap; - GCPtr temp_gc = NULL; /* 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. */ - goto fail; + goto wide_line; } if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { glamor_fallback @@ -107,69 +100,40 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, } gc->ops->PolyFillRect(drawable, gc, n - 1, rects); free(rects); - return; + return TRUE; fail: - for (i = 0; i < n; i++) { - if (x_min > points[i].x) - x_min = points[i].x; - if (x_max < points[i].x) - x_max = points[i].x; - - if (y_min > points[i].y) - y_min = points[i].y; - if (y_max < points[i].y) - y_max = points[i].y; - } - - temp_pixmap = glamor_create_pixmap(drawable->pScreen, - x_max - x_min + 1, - y_max - y_min + 1, - drawable->depth, 0); - if (temp_pixmap) { - temp_dest = &temp_pixmap->drawable; - temp_gc = - GetScratchGC(temp_dest->depth, temp_dest->pScreen); - ValidateGC(temp_dest, temp_gc); - for (i = 0; i < n; i++) { - points[i].x -= x_min; - points[i].y -= y_min; - } - (void) glamor_copy_area(drawable, - temp_dest, - temp_gc, - x_min, y_min, - x_max - x_min + 1, - y_max - y_min + 1, 0, 0); - - } else - temp_dest = drawable; + if (!fallback + && glamor_ddx_fallback_check_pixmap(drawable) + && glamor_ddx_fallback_check_gc(gc)) + return FALSE; if (gc->lineWidth == 0) { - if (glamor_prepare_access(temp_dest, GLAMOR_ACCESS_RW)) { + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { - fbPolyLine(temp_dest, gc, mode, n, points); + fbPolyLine(drawable, gc, mode, n, points); glamor_finish_access_gc(gc); } - glamor_finish_access(temp_dest, GLAMOR_ACCESS_RW); + glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } } else { +wide_line: /* fb calls mi functions in the lineWidth != 0 case. */ fbPolyLine(drawable, gc, mode, n, points); } - if (temp_dest != drawable) { - (void) glamor_copy_area(temp_dest, - drawable, - temp_gc, - 0, 0, - x_max - x_min + 1, - y_max - y_min + 1, x_min, y_min); - glamor_destroy_pixmap(temp_pixmap); - for (i = 0; i < n; i++) { - points[i].x += x_min; - points[i].y += y_min; - } - - FreeScratchGC(temp_gc); - } + return TRUE; +} + +void +glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points) +{ + _glamor_poly_lines(drawable, gc, mode, n, points, TRUE); +} + +Bool +glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n, + DDXPointPtr points) +{ + return _glamor_poly_lines(drawable, gc, mode, n, points, FALSE); } diff --git a/glamor/glamor_polyops.c b/glamor/glamor_polyops.c new file mode 100644 index 000000000..6188bb23f --- /dev/null +++ b/glamor/glamor_polyops.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glamor_priv.h" + +static Bool +_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_gc(pGC) + && glamor_ddx_fallback_check_pixmap(pDrawable)) + goto fail; + glamor_prepare_access_gc(pGC); + glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); + fbPolyPoint(pDrawable, pGC, mode, npt, ppt); + glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + glamor_finish_access_gc(pGC); + return TRUE; + +fail: + return FALSE; +} + +void +glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt) +{ + _glamor_poly_point(pDrawable, pGC, mode, npt, ppt, TRUE); +} + +Bool +glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt) +{ + return _glamor_poly_point(pDrawable, pGC, mode, npt, ppt, FALSE); +} + +static Bool +_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_gc(pGC) + && glamor_ddx_fallback_check_pixmap(pDrawable)) + goto fail; + /* For lineWidth is not zero, fb calls to mi functions. */ + if (pGC->lineWidth == 0) { + glamor_prepare_access_gc(pGC); + glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); + fbPolySegment(pDrawable, pGC, nseg, pSeg); + glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + glamor_finish_access_gc(pGC); + } else + fbPolySegment(pDrawable, pGC, nseg, pSeg); + + return TRUE; + +fail: + return FALSE; +} + +void +glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg) +{ + _glamor_poly_segment(pDrawable, pGC, nseg, pSeg, TRUE); +} + +Bool +glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg) +{ + return _glamor_poly_segment(pDrawable, pGC, nseg, pSeg, FALSE); +} + +static Bool +_glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt, Bool fallback) +{ + if (!fallback + && glamor_ddx_fallback_check_gc(pGC) + && glamor_ddx_fallback_check_pixmap(pDrawable)) + goto fail; + /* For lineWidth is not zero, fb calls to mi functions. */ + if (pGC->lineWidth == 0) { + glamor_prepare_access_gc(pGC); + glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); + fbPolyLine(pDrawable, pGC, mode, npt, ppt); + glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + glamor_finish_access_gc(pGC); + } else + fbPolyLine(pDrawable, pGC, mode, npt, ppt); + + return TRUE; + +fail: + return FALSE; +} + +void +glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt) +{ + _glamor_poly_line(pDrawable, pGC, mode, npt, ppt, TRUE); +} + +Bool +glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt) +{ + return _glamor_poly_line(pDrawable, pGC, mode, npt, ppt, FALSE); +} + diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 72d7867c3..4bd169b30 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -550,12 +550,42 @@ void glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d); - void glamor_add_traps(PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntrap, xTrap * traps); +RegionPtr +glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitPlane); + +void +glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase); + +void +glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase); + +void +glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, int w, int h, int x, int y); + +void +glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt); + +void +glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg); + +void +glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr ppt); + #include"glamor_utils.h" /* Dynamic pixmap upload to texture if needed. From 8a4758a358e56b1db481607ff3f7e9375238e5d8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 4 Jan 2012 13:11:52 +0800 Subject: [PATCH 257/462] Need to check pixmap priv before touch its field. As now the pixmap may be allocated by DDX and doesn't have a valid pixmap private field. We must check pixmap private pointer before touch its field value. If a pixmap doesn't have a non-NULL private pointer, it doesn't have a valid FBO. Signed-off-by: Zhigang Gong --- glamor/glamor_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 4d47f57ae..9eea70e11 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -176,7 +176,7 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) #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) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == 1) #define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ From 057f52a04d47e6ca5f6dead9c1bc71765d4c7ae8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 4 Jan 2012 14:34:39 +0800 Subject: [PATCH 258/462] Track all picture's drawable pict format. Even if a picture's pixmap is a pure in memory pixmap, we still need to track its format. The reason is we may need to upload this drawable to texture thus we need to know its real picture format. As to the MACRO to check whether a pixmap is a picture, we should check whether the priv is non-NULL before we touch its field. Signed-off-by: Zhigang Gong --- glamor/glamor_picture.c | 8 ++++++++ glamor/glamor_utils.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 940c9d75a..2f9bc81ed 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -58,6 +58,14 @@ glamor_create_picture(PicturePtr picture) glamor_get_screen_private(picture->pDrawable->pScreen); pixmap = glamor_get_drawable_pixmap(picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!pixmap_priv) { + /* We must create a pixmap priv to track the picture format even + * if the pixmap is a pure in memory pixmap. The reason is that + * we may need to upload this pixmap to a texture on the fly. During + * the uploading, we need to know the picture format. */ + glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); + pixmap_priv = glamor_get_pixmap_private(pixmap); + } if (pixmap_priv) { pixmap_priv->is_picture = 1; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 9eea70e11..dfb77113e 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -175,7 +175,7 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) || _depth_ == 32) -#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv->is_picture == 1) +#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1) #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == 1) #define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ From e1789893e5fe07fdbd8f21b7fa8a15f6db066592 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 4 Jan 2012 14:37:37 +0800 Subject: [PATCH 259/462] get_spans: Check whether have a valid fbo before check format. If a pixmap is a pure in-memory pixmap, we do not need to check its format. Format checking has more overhead than checking FBO, so we change to check fbo firtly. Signed-off-by: Zhigang Gong --- glamor/glamor_setspans.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 360ca37af..26e774bc6 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -37,6 +37,7 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, Bool fallback) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *dest_pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; @@ -47,6 +48,12 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, BoxRec *pbox; int x_off, y_off; + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + glamor_fallback("pixmap has no fbo.\n"); + goto fail; + } + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { glamor_fallback("ES2 fallback.\n"); goto fail; @@ -61,9 +68,7 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, } - if (glamor_set_destination_pixmap(dest_pixmap)) - goto fail; - + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); glamor_validate_pixmap(dest_pixmap); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; From a65e1c736aaa1bb2440a83c42c0410d9d9b58007 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 4 Jan 2012 14:40:24 +0800 Subject: [PATCH 260/462] Reduce the double check of pixmap's private pointer. As we now add the checking to the Macro, we don't need to check the pointer outside the Macro. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 2 +- glamor/glamor_core.c | 2 +- glamor/glamor_fill.c | 2 +- glamor/glamor_getspans.c | 2 +- glamor/glamor_pixmap.c | 2 +- glamor/glamor_putimage.c | 2 +- glamor/glamor_render.c | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 049979afd..4310a0479 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -317,7 +317,7 @@ _glamor_copy_n_to_n(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; - if (!dst_pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); goto fail; diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f865ece46..8ce2104a1 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -264,7 +264,7 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) glamor_get_screen_private(drawable->pScreen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return; if (access_mode != GLAMOR_ACCESS_RO) { diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index d36313ae3..da8097a10 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -149,7 +149,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat color[4]; float vertices[8]; GLfloat xscale, yscale; - if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("dest %p has no fbo.\n", pixmap); goto fail; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 4d4108da3..be81fbb9c 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -50,7 +50,7 @@ _glamor_get_spans(DrawablePtr drawable, uint8_t *readpixels_dst = (uint8_t *) dst; int x_off, y_off; - if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); goto fail; } diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 9559d1731..b56afc0b9 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -646,7 +646,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; screen = pixmap->drawable.pScreen; - if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 7967e25a7..f4b174d5e 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -265,7 +265,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, goto fail; } - if (!pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("has no fbo.\n"); goto fail; } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 4a2a4388a..487171c8e 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -754,7 +754,7 @@ glamor_composite_with_shader(CARD8 op, GLfloat source_solid_color[4], mask_solid_color[4]; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - if (!dest_pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; } @@ -1220,7 +1220,7 @@ _glamor_composite(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ - if (!dest_pixmap_priv || !GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { goto fail; } From 2511a00cdd576512f5d7f45707a4a725df2f4618 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 5 Jan 2012 14:26:01 +0800 Subject: [PATCH 261/462] Fixed a configure bug. Should check the enable-glamor-gles2 before use the variable. And should include the config.h as the GLAMOR_GLES2 macro is defined there. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 4 ++++ glamor/glamor_priv.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 7eca5ad42..28a48ca78 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -27,6 +27,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef HAVE_DIX_CONFIG_H #include #endif diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 4bd169b30..08db6316f 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -27,6 +27,10 @@ #ifndef GLAMOR_PRIV_H #define GLAMOR_PRIV_H +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef HAVE_DIX_CONFIG_H #include #include From 9dafd6fce547a6824c1de98d4309f8f2197ebbd0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 8 Jan 2012 01:14:12 +0800 Subject: [PATCH 262/462] glamor-composite: Optimize the computation of composite region. Computing the composite region at the composite_with_shader is very inefficient. As when we call to here from the glamor_glyph's temproary picture, we don't need to compute this region at all. So we move this computing out from this function and do that at the glamor_composite function. This can get about 5% performance gain for aa10text/rgb10text. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 204 +++++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 98 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 487171c8e..4f09bbf19 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1023,98 +1023,57 @@ glamor_composite_with_shader(CARD8 op, 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; + x_dest = rects->x_dst + dest_x_off; + y_dest = rects->y_dst + dest_y_off; + x_source = rects->x_src + source_x_off;; + y_source = rects->y_src + source_y_off; + x_mask = rects->x_mask + mask_x_off; + y_mask = rects->y_mask + mask_y_off; 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_set_normalize_vcoords(dst_xscale, + dst_yscale, + x_dest, y_dest, + x_dest + width, y_dest + height, + glamor_priv->yInverted, + vertices); + + if (key.source != SHADER_SOURCE_SOLID) { + if (source->transform) + glamor_set_transformed_normalize_tcoords(src_matrix, src_xscale, + src_yscale, x_source, y_source, + x_source + width, y_source + height, + glamor_priv->yInverted, + source_texcoords); + else + glamor_set_normalize_tcoords(src_xscale, src_yscale, + x_source, y_source, + x_source + width, y_source + height, + glamor_priv->yInverted, + source_texcoords); } - 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++) { - int vx1 = box[i].x1 + dest_x_off; - int vx2 = box[i].x2 + dest_x_off; - int vy1 = box[i].y1 + dest_y_off; - int vy2 = box[i].y2 + dest_y_off; - glamor_set_normalize_vcoords(dst_xscale, - dst_yscale, vx1, - vy1, vx2, vy2, - glamor_priv->yInverted, - vertices); - - 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; - if (source->transform) - glamor_set_transformed_normalize_tcoords - (src_matrix, src_xscale, - src_yscale, tx1, ty1, - tx2, ty2, - glamor_priv->yInverted, - source_texcoords); - else - glamor_set_normalize_tcoords - (src_xscale, src_yscale, - tx1, ty1, tx2, ty2, - glamor_priv->yInverted, - source_texcoords); - } - - 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; - if (mask->transform) - glamor_set_transformed_normalize_tcoords - (mask_matrix, - mask_xscale, - mask_yscale, tx1, ty1, - tx2, ty2, - glamor_priv->yInverted, - mask_texcoords); - else - glamor_set_normalize_tcoords - (mask_xscale, - mask_yscale, tx1, ty1, - tx2, ty2, - glamor_priv->yInverted, - mask_texcoords); - } - glamor_emit_composite_rect(screen, - source_texcoords, - mask_texcoords, - vertices); + if (key.mask != SHADER_MASK_NONE + && key.mask != SHADER_MASK_SOLID) { + if (mask->transform) + glamor_set_transformed_normalize_tcoords(mask_matrix, + mask_xscale, + mask_yscale, x_mask, y_mask, + x_mask + width, y_mask + height, + glamor_priv->yInverted, + mask_texcoords); + else + glamor_set_normalize_tcoords(mask_xscale, + mask_yscale, x_mask, y_mask, + x_mask + width, y_mask + height, + glamor_priv->yInverted, + mask_texcoords); } + glamor_emit_composite_rect(screen, + source_texcoords, + mask_texcoords, + vertices); rects++; } glamor_flush_composite_rects(screen); @@ -1123,7 +1082,6 @@ glamor_composite_with_shader(CARD8 op, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); - REGION_UNINIT(dst->pDrawable->pScreen, ®ion); dispatch->glDisable(GL_BLEND); #ifndef GLAMOR_GLES2 dispatch->glActiveTexture(GL_TEXTURE0); @@ -1207,11 +1165,16 @@ _glamor_composite(CARD8 op, PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; PicturePtr temp_src = source, temp_mask = mask; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; - glamor_composite_rect_t rect; + glamor_composite_rect_t rect[10]; + glamor_composite_rect_t *prect = rect; + int prect_size = ARRAY_SIZE(rect); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; Bool ret = TRUE; + RegionRec region; + BoxPtr box; + int nbox, i, ok; x_temp_src = x_source; y_temp_src = y_source; @@ -1325,16 +1288,59 @@ _glamor_composite(CARD8 op, height)) goto done; } - rect.x_src = x_temp_src; - rect.y_src = y_temp_src; - rect.x_mask = x_temp_mask; - rect.y_mask = y_temp_mask; - rect.x_dst = x_dest; - rect.y_dst = y_dest; - rect.width = width; - rect.height = height; - if (glamor_composite_with_shader - (op, temp_src, temp_mask, dest, 1, &rect)) + x_dest += dest->pDrawable->x; + y_dest += dest->pDrawable->y; + if (temp_src->pDrawable) { + x_temp_src += temp_src->pDrawable->x; + y_temp_src += temp_src->pDrawable->y; + } + if (temp_mask && temp_mask->pDrawable) { + x_temp_mask += temp_mask->pDrawable->x; + y_temp_mask += temp_mask->pDrawable->y; + } + if (!miComputeCompositeRegion(®ion, + temp_src, temp_mask, dest, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, + x_dest, y_dest, width, + height)) + goto done; + + box = REGION_RECTS(®ion); + nbox = REGION_NUM_RECTS(®ion); + + if (nbox > ARRAY_SIZE(rect)) { + prect = calloc(nbox, sizeof(*prect)); + if (prect) + prect_size = nbox; + else { + prect = rect; + prect_size = ARRAY_SIZE(rect); + } + } + while(nbox) { + int box_cnt; + box_cnt = nbox > prect_size ? prect_size : nbox; + for (i = 0; i < box_cnt; i++) { + prect[i].x_src = box[i].x1 + x_temp_src - x_dest; + prect[i].y_src = box[i].y1 + y_temp_src - y_dest; + prect[i].x_mask = box[i].x1 + x_temp_mask - x_dest; + prect[i].y_mask = box[i].y1 + y_temp_mask - y_dest; + prect[i].x_dst = box[i].x1; + prect[i].y_dst = box[i].y1; + prect[i].width = box[i].x2 - box[i].x1; + prect[i].height = box[i].y2 - box[i].y1; + } + ok = glamor_composite_with_shader(op, temp_src, temp_mask, + dest, box_cnt, prect); + if (!ok) + break; + nbox -= box_cnt; + box += box_cnt; + } + + REGION_UNINIT(dest->pDrawable->pScreen, ®ion); + if (ok) goto done; fail: @@ -1391,6 +1397,8 @@ fallback: FreePicture(temp_src, 0); if (temp_mask != mask) FreePicture(temp_mask, 0); + if (prect != rect) + free(prect); return ret; } From 4cd07871a417b15b0382c07fecec497e93697a5d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 8 Jan 2012 08:45:08 +0800 Subject: [PATCH 263/462] glamor-composite: Use glDrawElements to reduce the count of vertices. To split a rectangle (0,1,2,3) to two separated triangles need to feed 6 vertices, (0,1,2) and (0,2,3). use glDrawElements can reuse the shared vertices. Signed-off-by: Zhigang Gong --- glamor/glamor_gl_dispatch.c | 2 ++ glamor/glamor_gl_dispatch.h | 6 +++- glamor/glamor_priv.h | 2 +- glamor/glamor_render.c | 59 ++++++++++++++++++++++++++----------- 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index 788562c5e..5a47b4576 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -16,6 +16,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glViewport, get_proc_address); INIT_FUNC(dispatch, glRasterPos2i, get_proc_address); INIT_FUNC(dispatch, glDrawArrays, get_proc_address); + INIT_FUNC(dispatch, glDrawElements, get_proc_address); INIT_FUNC(dispatch, glReadPixels, get_proc_address); INIT_FUNC(dispatch, glDrawPixels, get_proc_address); INIT_FUNC(dispatch, glPixelStorei, get_proc_address); @@ -37,6 +38,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glGenBuffers, get_proc_address); INIT_FUNC(dispatch, glBufferData, get_proc_address); INIT_FUNC(dispatch, glMapBuffer, get_proc_address); + INIT_FUNC(dispatch, glMapBufferRange, get_proc_address); INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); INIT_FUNC(dispatch, glBindBuffer, get_proc_address); INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index 5f1831a7e..8fcb3dc96 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -10,6 +10,9 @@ typedef struct glamor_gl_dispatch { /* Vertex Array */ void (*glDrawArrays) (GLenum mode, GLint first, GLsizei count); + /* Elements Array*/ + void (*glDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); + /* Raster functions */ void (*glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, @@ -55,7 +58,8 @@ typedef struct glamor_gl_dispatch { void (*glBufferData) (GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); GLvoid *(*glMapBuffer) (GLenum target, GLenum access); - GLboolean(*glUnmapBuffer) (GLenum target); + GLvoid *(*glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + GLboolean(*glUnmapBuffer) (GLenum target); void (*glBindBuffer) (GLenum target, GLuint buffer); void (*glDeleteBuffers) (GLsizei n, const GLuint * buffers); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 08db6316f..f3b0996bf 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -158,7 +158,7 @@ typedef struct glamor_screen_private { int yInverted; int screen_fbo; - GLuint vbo; + GLuint vbo, ebo; int vbo_offset; int vbo_size; char *vb; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 4f09bbf19..29c33b08f 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -288,7 +288,7 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct return shader; } -#define GLAMOR_COMPOSITE_VBO_SIZE 8192 +#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 static void glamor_reset_composite_vbo(ScreenPtr screen) @@ -296,18 +296,44 @@ glamor_reset_composite_vbo(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_priv->vbo_offset = 0; - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_SIZE; + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2; glamor_priv->render_nr_verts = 0; } +static void +glamor_init_eb(unsigned short *eb, int vert_cnt) +{ + int i, j; + for(i = 0, j = 0; j < vert_cnt; i += 6, j += 4) + { + eb[i] = j; + eb[i + 1] = j + 1; + eb[i + 2] = j + 2; + eb[i + 3] = j; + eb[i + 4] = j + 2; + eb[i + 5] = j + 3; + } +} + void glamor_init_composite_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_priv->vb = malloc(GLAMOR_COMPOSITE_VBO_SIZE); - assert(glamor_priv->vb != NULL); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + unsigned short *eb; + + dispatch->glGenBuffers(1, &glamor_priv->vbo); + dispatch->glGenBuffers(1, &glamor_priv->ebo); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, + GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2, + NULL, GL_DYNAMIC_DRAW); + eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); glamor_reset_composite_vbo(screen); } @@ -542,6 +568,12 @@ glamor_setup_composite_vbo(ScreenPtr screen) glamor_priv->vb_stride += 2 * sizeof(float); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2, + NULL, GL_DYNAMIC_DRAW); + + glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, glamor_priv->vb_stride, @@ -609,11 +641,9 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!glamor_priv->render_nr_verts) return; - dispatch->glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, - glamor_priv->vb, GL_STREAM_DRAW); - - dispatch->glDrawArrays(GL_TRIANGLES, 0, - glamor_priv->render_nr_verts); + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); glamor_reset_composite_vbo(screen); } @@ -627,15 +657,12 @@ glamor_emit_composite_rect(ScreenPtr screen, glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (glamor_priv->vbo_offset + 6 * glamor_priv->vb_stride > + if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > glamor_priv->vbo_size) { glamor_flush_composite_rects(screen); } if (glamor_priv->vbo_offset == 0) { - if (glamor_priv->vbo == 0) - dispatch->glGenBuffers(1, &glamor_priv->vbo); - glamor_setup_composite_vbo(screen); } @@ -645,10 +672,6 @@ glamor_emit_composite_rect(ScreenPtr screen, 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, 0); - glamor_emit_composite_vert(screen, src_coords, mask_coords, - dst_coords, 2); glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 3); } @@ -969,7 +992,6 @@ glamor_composite_with_shader(CARD8 op, dispatch->glUseProgram(shader->prog); - if (key.source == SHADER_SOURCE_SOLID) { glamor_set_composite_solid(dispatch, source_solid_color, shader->source_uniform_location); @@ -1079,6 +1101,7 @@ glamor_composite_with_shader(CARD8 op, glamor_flush_composite_rects(screen); dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); From a74596be0e7e02b43fb0db844b71b68f384ab599 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 8 Jan 2012 08:50:41 +0800 Subject: [PATCH 264/462] Set filter to GL_NEAREST by default. This is the fastest filter and let's use it by default. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 17 +++++++++++++++++ glamor/glamor_putimage.c | 8 ++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index b56afc0b9..884dd83a7 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -243,6 +243,10 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); @@ -584,6 +588,13 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, source->drawable.width, source->drawable.height, 0, *format, *type, @@ -601,6 +612,12 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index f4b174d5e..f285d957c 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -313,6 +313,10 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glGenTextures(1, &tex); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { iformat = format; @@ -323,10 +327,6 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); From 96085017c8da96e6d882c87b69186f5aba20131d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Jan 2012 05:01:48 +0800 Subject: [PATCH 265/462] Consolidate the choose of internal texture format to one function. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 15 +-------------- glamor/glamor_pixmap.c | 19 +++---------------- glamor/glamor_utils.h | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index bbcf94258..3634e70da 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -169,20 +169,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w == 0 || h == 0 || type == GLAMOR_MEMORY) return pixmap; - switch (depth) { -#if 0 - case 8: - format = GL_ALPHA; - break; -#endif - case 24: - format = GL_RGB; - break; - default: - format = GL_RGBA; - break; - } - + gl_iformat_for_depth(depth, &format); /* Create the texture used to store the pixmap's data. */ dispatch->glGenTextures(1, &tex); dispatch->glBindTexture(GL_TEXTURE_2D, tex); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 884dd83a7..f43a90b3c 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -221,23 +221,10 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, void *texels; GLenum iformat; - switch (pixmap->drawable.depth) { -#if 0 - case 8: - iformat = GL_ALPHA; - break; -#endif - case 24: - iformat = GL_RGB; - break; - default: - iformat = GL_RGBA; - break; - } - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) iformat = format; - } + else + gl_iformat_for_depth(pixmap->drawable.depth, &iformat); stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index dfb77113e..49c7e1de6 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -224,6 +224,26 @@ format_for_depth(int depth) } } +static inline void +gl_iformat_for_depth(int depth, GLenum * format) +{ + switch (depth) { +#if 0 + case 8: + *format = GL_ALPHA; + break; +#endif + case 24: + *format = GL_RGB; + break; + default: + *format = GL_RGBA; + break; + } +} + + + static inline CARD32 format_for_pixmap(PixmapPtr pixmap) { From 42a0261cb3065200887f81816b1bc3850593da4c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Jan 2012 05:03:08 +0800 Subject: [PATCH 266/462] glamor_getimage: Add the optimization path of getImage. This optimization will only call glReadPixels once. It should get some performance gain. But it seems it even get worse performance at SNB, disable it by default. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 81 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 7a9280b43..086ec4b6d 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -34,11 +34,88 @@ static Bool -_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, +_glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d, Bool fallback) { - miGetImage(pDrawable, x, y, w, h, format, planeMask, d); + PixmapPtr pixmap; + struct glamor_pixmap_private *pixmap_priv; + struct glamor_screen_private *glamor_priv; + int x_off, y_off; + GLenum tex_format, tex_type; + int no_alpha, no_revert; + PixmapPtr temp_pixmap = NULL; + glamor_gl_dispatch * dispatch; + + goto fall_back; + if (format != ZPixmap) + goto fall_back; + + pixmap = glamor_get_drawable_pixmap(drawable); + if (!glamor_set_planemask(pixmap, planeMask)) { + glamor_fallback + ("Failedto set planemask in glamor_solid.\n"); + goto fall_back; + } + glamor_priv = glamor_get_screen_private(drawable->pScreen); + pixmap_priv = glamor_get_pixmap_private(pixmap); + dispatch = &glamor_priv->dispatch; + + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto fall_back; + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &tex_format, + &tex_type, + &no_alpha, + &no_revert)) { + glamor_fallback("unknown depth. %d \n", drawable->depth); + goto fall_back; + } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + glamor_validate_pixmap(pixmap); + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + /* XXX prepare whole pixmap is not efficient. */ + temp_pixmap = + glamor_es2_pixmap_read_prepare(pixmap, &tex_format, + &tex_type, no_alpha, + no_revert); + pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + } + + int row_length = PixmapBytePad(w, drawable->depth); + row_length = (row_length * 8) / drawable->bitsPerPixel; + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + } else { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); + } + + if (glamor_priv->yInverted) + dispatch->glReadPixels(x + x_off, + y + y_off, + w, h, + tex_format, + tex_type, d); + else + dispatch->glReadPixels(x + x_off, + pixmap->drawable.height - 1 - (y + y_off), + w, + h, + tex_format, + tex_type, d); + if (temp_pixmap) + glamor_destroy_pixmap(temp_pixmap); + return TRUE; + +fall_back: + miGetImage(drawable, x, y, w, h, format, planeMask, d); return TRUE; } From 069a6d1746ef4c180f48a75e655e5e06e33327b5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Jan 2012 07:11:26 +0800 Subject: [PATCH 267/462] glamor_composite: Allocate VBO on demand. Use a fixed VBO is not efficient. Some times we may only has less than 100 verts, and some times we may have larger than 4K verts. We change it to allocate VBO buffer dynamically, and this can bring about 10% performance gain for both aa10text/rgb10text and some cairo benchmarks. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 178 ++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 92 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 29c33b08f..6a7057afb 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -290,16 +290,6 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct #define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 -static void -glamor_reset_composite_vbo(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_priv->vbo_offset = 0; - glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2; - glamor_priv->render_nr_verts = 0; -} - static void glamor_init_eb(unsigned short *eb, int vert_cnt) { @@ -334,7 +324,6 @@ glamor_init_composite_shaders(ScreenPtr screen) glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - glamor_reset_composite_vbo(screen); } static Bool @@ -395,7 +384,6 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glamor_pixmap_private * pixmap_priv) { - unsigned int no_alpha, no_revert, format, type; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; @@ -555,12 +543,17 @@ glamor_composite_with_copy(CARD8 op, } static void -glamor_setup_composite_vbo(ScreenPtr screen) +glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_priv->vbo_offset = 0; + glamor_priv->vbo_offset = 0; + glamor_priv->render_nr_verts = 0; + glamor_priv->vbo_size = n_verts * sizeof(float) * 2; + glamor_priv->vb_stride = 2 * sizeof(float); if (glamor_priv->has_source_coords) glamor_priv->vb_stride += 2 * sizeof(float); @@ -569,7 +562,7 @@ glamor_setup_composite_vbo(ScreenPtr screen) dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); dispatch->glBufferData(GL_ARRAY_BUFFER, - GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2, + n_verts * sizeof(float) * 2, NULL, GL_DYNAMIC_DRAW); glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); @@ -644,7 +637,6 @@ glamor_flush_composite_rects(ScreenPtr screen) dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, GL_UNSIGNED_SHORT, NULL); - glamor_reset_composite_vbo(screen); } static void @@ -653,19 +645,6 @@ 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_gl_dispatch *dispatch = &glamor_priv->dispatch; - - if (glamor_priv->vbo_offset + 4 * glamor_priv->vb_stride > - glamor_priv->vbo_size) { - glamor_flush_composite_rects(screen); - } - - if (glamor_priv->vbo_offset == 0) { - 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, @@ -676,7 +655,6 @@ glamor_emit_composite_rect(ScreenPtr screen, 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}, @@ -763,10 +741,7 @@ glamor_composite_with_shader(CARD8 op, 1, src_yscale = 1; 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; @@ -776,6 +751,8 @@ glamor_composite_with_shader(CARD8 op, float src_matrix[9], mask_matrix[9]; GLfloat source_solid_color[4], mask_solid_color[4]; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + int vert_stride = 4; + int nrect_max; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); @@ -1025,6 +1002,7 @@ glamor_composite_with_shader(CARD8 op, pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); glamor_picture_get_matrixf(source, src_matrix); + vert_stride += 4; } if (glamor_priv->has_mask_coords) { @@ -1033,72 +1011,89 @@ glamor_composite_with_shader(CARD8 op, pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); glamor_picture_get_matrixf(mask, mask_matrix); + vert_stride += 4; } - while (nrect--) { - INT16 x_source; - INT16 y_source; - INT16 x_mask; - INT16 y_mask; - INT16 x_dest; - INT16 y_dest; - CARD16 width; - CARD16 height; + nrect_max = (vert_stride * nrect) > GLAMOR_COMPOSITE_VBO_VERT_CNT ? + (GLAMOR_COMPOSITE_VBO_VERT_CNT / 6) : nrect; - x_dest = rects->x_dst + dest_x_off; - y_dest = rects->y_dst + dest_y_off; - x_source = rects->x_src + source_x_off;; - y_source = rects->y_src + source_y_off; - x_mask = rects->x_mask + mask_x_off; - y_mask = rects->y_mask + mask_y_off; - width = rects->width; - height = rects->height; + while(nrect) { + int mrect, rect_processed; - glamor_set_normalize_vcoords(dst_xscale, - dst_yscale, - x_dest, y_dest, - x_dest + width, y_dest + height, - glamor_priv->yInverted, - vertices); + mrect = nrect > nrect_max ? nrect_max : nrect ; + glamor_setup_composite_vbo(screen, mrect * vert_stride); + rect_processed = mrect; - if (key.source != SHADER_SOURCE_SOLID) { - if (source->transform) - glamor_set_transformed_normalize_tcoords(src_matrix, src_xscale, - src_yscale, x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, - source_texcoords); - else - glamor_set_normalize_tcoords(src_xscale, src_yscale, - x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, - source_texcoords); + while (mrect--) { + 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 + dest_x_off; + y_dest = rects->y_dst + dest_y_off; + x_source = rects->x_src + source_x_off;; + y_source = rects->y_src + source_y_off; + x_mask = rects->x_mask + mask_x_off; + y_mask = rects->y_mask + mask_y_off; + width = rects->width; + height = rects->height; + + glamor_set_normalize_vcoords(dst_xscale, + dst_yscale, + x_dest, y_dest, + x_dest + width, y_dest + height, + glamor_priv->yInverted, + vertices); + + if (key.source != SHADER_SOURCE_SOLID) { + if (source->transform) + glamor_set_transformed_normalize_tcoords + (src_matrix, src_xscale, + src_yscale, x_source, y_source, + x_source + width, y_source + height, + glamor_priv->yInverted, + source_texcoords); + else + glamor_set_normalize_tcoords + (src_xscale, src_yscale, + x_source, y_source, + x_source + width, y_source + height, + glamor_priv->yInverted, + source_texcoords); + } + + if (key.mask != SHADER_MASK_NONE + && key.mask != SHADER_MASK_SOLID) { + if (mask->transform) + glamor_set_transformed_normalize_tcoords + (mask_matrix, + mask_xscale, + mask_yscale, x_mask, y_mask, + x_mask + width, y_mask + height, + glamor_priv->yInverted, + mask_texcoords); + else + glamor_set_normalize_tcoords + (mask_xscale, + mask_yscale, x_mask, y_mask, + x_mask + width, y_mask + height, + glamor_priv->yInverted, + mask_texcoords); + } + glamor_emit_composite_rect(screen, + source_texcoords, + mask_texcoords, + vertices); + rects++; } - - if (key.mask != SHADER_MASK_NONE - && key.mask != SHADER_MASK_SOLID) { - if (mask->transform) - glamor_set_transformed_normalize_tcoords(mask_matrix, - mask_xscale, - mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, - mask_texcoords); - else - glamor_set_normalize_tcoords(mask_xscale, - mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, - mask_texcoords); - } - glamor_emit_composite_rect(screen, - source_texcoords, - mask_texcoords, - vertices); - rects++; + glamor_flush_composite_rects(screen); + nrect -= rect_processed; } - glamor_flush_composite_rects(screen); dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -1380,7 +1375,6 @@ _glamor_composite(CARD8 op, goto done; } -fallback: glamor_fallback ("from picts %p:%p %dx%d / %p:%p %d x %d (%c,%c) to pict %p:%p %dx%d (%c)\n", source, source->pDrawable, From 7329414bf2ca9873c04150a1d9386cf37f70b663 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Jan 2012 07:16:06 +0800 Subject: [PATCH 268/462] Silence a compilation warning. Signed-off-by: Zhigang Gong --- glamor/glamor_picture.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 2f9bc81ed..27c3fe85a 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -13,7 +13,6 @@ 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); From 8b943ce2030b02bb8d279ce2c284cb5d2910ced6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Jan 2012 12:50:39 +0800 Subject: [PATCH 269/462] Set glamor's initial version to 0.2.0. Signed-off-by: Zhigang Gong --- glamor/glamor_eglmodule.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c index 5281ff41d..4da57af93 100644 --- a/glamor/glamor_eglmodule.c +++ b/glamor/glamor_eglmodule.c @@ -24,6 +24,10 @@ * XFree86 Project. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "xf86Module.h" @@ -34,7 +38,7 @@ static XF86ModuleVersionInfo VersRec = { MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, - 1, 0, 0, + PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, ABI_CLASS_ANSIC, /* Only need the ansic layer */ ABI_ANSIC_VERSION, MOD_CLASS_NONE, From d7352d57b9ceb809d47c922ed8c820a44f8a0ee5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 10 Jan 2012 15:24:36 +0800 Subject: [PATCH 270/462] Add glFinish after glFlush. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 + glamor/glamor_gl_dispatch.c | 1 + glamor/glamor_gl_dispatch.h | 1 + 3 files changed, 3 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 3634e70da..6ee11f7b1 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -224,6 +224,7 @@ glamor_block_handler(ScreenPtr screen) glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; dispatch->glFlush(); + dispatch->glFinish(); } static void diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index 5a47b4576..f8516b4d9 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -27,6 +27,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glBindTexture, get_proc_address); INIT_FUNC(dispatch, glTexSubImage2D, get_proc_address); INIT_FUNC(dispatch, glFlush, get_proc_address); + INIT_FUNC(dispatch, glFinish, get_proc_address); INIT_FUNC(dispatch, glGetIntegerv, get_proc_address); INIT_FUNC(dispatch, glGetString, get_proc_address); INIT_FUNC(dispatch, glScissor, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index 8fcb3dc96..a8a699b5c 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -41,6 +41,7 @@ typedef struct glamor_gl_dispatch { const GLvoid * pixels); /* MISC */ void (*glFlush) (void); + void (*glFinish) (void); void (*glGetIntegerv) (GLenum pname, GLint * params); const GLubyte *(*glGetString) (GLenum name); void (*glScissor) (GLint x, GLint y, GLsizei width, From bdd72da0c525faf2aac38a7a8afa1cd88cd8dc1b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 10 Jan 2012 17:04:48 +0800 Subject: [PATCH 271/462] Release previous textre/fb when bind a new texture to a pixmap. As we want to support DRI2 drawable which may create a new textured_drm to a pre-existing texture_only pixmap, we have to add this logical. Signed-off-by: Zhigang Gong Tested-by: He Junyan --- glamor/glamor.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 6ee11f7b1..8f74daa21 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -86,6 +86,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv == NULL) { @@ -96,6 +97,12 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) pixmap_priv->glamor_priv = glamor_priv; } + if (pixmap_priv->fb) + dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); + + if (pixmap_priv->tex) + dispatch->glDeleteTextures(1, &pixmap_priv->tex); + pixmap_priv->tex = tex; /* Create a framebuffer object wrapping the texture so that we can render From 28fcd7cd01edfdf68c370e6c6ad0238d45477b3f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 13 Jan 2012 11:18:28 +0800 Subject: [PATCH 272/462] Rearrange data structure and remove unused fileds. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 60 ++++++++++++++--------------- glamor/glamor_picture.c | 5 ++- glamor/glamor_priv.h | 85 +++++++++++++++++++++-------------------- 3 files changed, 76 insertions(+), 74 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 8f74daa21..74c23c6a5 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -343,60 +343,60 @@ glamor_init(ScreenPtr screen, unsigned int flags) goto fail; } - glamor_priv->saved_close_screen = screen->CloseScreen; + glamor_priv->saved_procs.close_screen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; - glamor_priv->saved_create_gc = screen->CreateGC; + glamor_priv->saved_procs.create_gc = screen->CreateGC; screen->CreateGC = glamor_create_gc; - glamor_priv->saved_create_pixmap = screen->CreatePixmap; + glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; screen->CreatePixmap = glamor_create_pixmap; - glamor_priv->saved_destroy_pixmap = screen->DestroyPixmap; + glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; - glamor_priv->saved_get_spans = screen->GetSpans; + glamor_priv->saved_procs.get_spans = screen->GetSpans; screen->GetSpans = glamor_get_spans; - glamor_priv->saved_get_image = screen->GetImage; + glamor_priv->saved_procs.get_image = screen->GetImage; screen->GetImage = glamor_get_image; - glamor_priv->saved_change_window_attributes = + glamor_priv->saved_procs.change_window_attributes = screen->ChangeWindowAttributes; screen->ChangeWindowAttributes = glamor_change_window_attributes; - glamor_priv->saved_copy_window = screen->CopyWindow; + glamor_priv->saved_procs.copy_window = screen->CopyWindow; screen->CopyWindow = glamor_copy_window; - glamor_priv->saved_bitmap_to_region = + glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; screen->BitmapToRegion = glamor_bitmap_to_region; } #ifdef RENDER if (flags & GLAMOR_USE_PICTURE_SCREEN) { - glamor_priv->saved_composite = ps->Composite; + glamor_priv->saved_procs.composite = ps->Composite; ps->Composite = glamor_composite; - glamor_priv->saved_trapezoids = ps->Trapezoids; + glamor_priv->saved_procs.trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; - glamor_priv->saved_glyphs = ps->Glyphs; + glamor_priv->saved_procs.glyphs = ps->Glyphs; ps->Glyphs = glamor_glyphs; - glamor_priv->saved_triangles = ps->Triangles; + glamor_priv->saved_procs.triangles = ps->Triangles; ps->Triangles = glamor_triangles; - glamor_priv->saved_addtraps = ps->AddTraps; + glamor_priv->saved_procs.addtraps = ps->AddTraps; ps->AddTraps = glamor_add_traps; - glamor_priv->saved_unrealize_glyph = ps->UnrealizeGlyph; + glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph; ps->UnrealizeGlyph = glamor_glyph_unrealize; } - glamor_priv->saved_create_picture = ps->CreatePicture; + glamor_priv->saved_procs.create_picture = ps->CreatePicture; ps->CreatePicture = glamor_create_picture; - glamor_priv->saved_destroy_picture = ps->DestroyPicture; + glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture; ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); #endif @@ -430,22 +430,22 @@ glamor_close_screen(int idx, ScreenPtr screen) PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif glamor_glyphs_fini(screen); - screen->CloseScreen = glamor_priv->saved_close_screen; - screen->CreateGC = glamor_priv->saved_create_gc; - screen->CreatePixmap = glamor_priv->saved_create_pixmap; - screen->DestroyPixmap = glamor_priv->saved_destroy_pixmap; - screen->GetSpans = glamor_priv->saved_get_spans; + screen->CloseScreen = glamor_priv->saved_procs.close_screen; + screen->CreateGC = glamor_priv->saved_procs.create_gc; + screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; + screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; + screen->GetSpans = glamor_priv->saved_procs.get_spans; screen->ChangeWindowAttributes = - glamor_priv->saved_change_window_attributes; - screen->CopyWindow = glamor_priv->saved_copy_window; - screen->BitmapToRegion = glamor_priv->saved_bitmap_to_region; + glamor_priv->saved_procs.change_window_attributes; + screen->CopyWindow = glamor_priv->saved_procs.copy_window; + screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; #ifdef RENDER if (ps) { - ps->Composite = glamor_priv->saved_composite; - 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; + ps->Composite = glamor_priv->saved_procs.composite; + ps->Trapezoids = glamor_priv->saved_procs.trapezoids; + ps->Glyphs = glamor_priv->saved_procs.glyphs; + ps->Triangles = glamor_priv->saved_procs.triangles; + ps->CreatePicture = glamor_priv->saved_procs.create_picture; } #endif if (glamor_priv->vb) diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 27c3fe85a..a9e3c267d 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -4,6 +4,7 @@ #include +#include "mipict.h" #include "glamor_priv.h" /* Upload picture to texture. We may need to flip the y axis or @@ -73,7 +74,7 @@ glamor_create_picture(PicturePtr picture) if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); } - return glamor_priv->saved_create_picture(picture); + return miCreatePicture(picture); } void @@ -95,7 +96,7 @@ glamor_destroy_picture(PicturePtr picture) pixmap_priv->is_picture = 0; pixmap_priv->pict_format = 0; } - glamor_priv->saved_destroy_picture(picture); + miDestroyPicture(picture); } void diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index f3b0996bf..90ed6bb40 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -124,7 +124,6 @@ enum glamor_gl_flavor { #define GLAMOR_CREATE_PIXMAP_CPU 0x100 -#define GLAMOR_NUM_GLYPH_CACHES 4 #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 typedef struct { @@ -137,46 +136,57 @@ typedef struct { #include "glamor_gl_dispatch.h" -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; - AddTrapsProcPtr saved_addtraps; - CreatePictureProcPtr saved_create_picture; - DestroyPictureProcPtr saved_destroy_picture; - UnrealizeGlyphProcPtr saved_unrealize_glyph; +struct glamor_saved_procs { + CloseScreenProcPtr close_screen; + CreateGCProcPtr create_gc; + CreatePixmapProcPtr create_pixmap; + DestroyPixmapProcPtr destroy_pixmap; + GetSpansProcPtr get_spans; + GetImageProcPtr get_image; + CompositeProcPtr composite; + TrapezoidsProcPtr trapezoids; + GlyphsProcPtr glyphs; + ChangeWindowAttributesProcPtr change_window_attributes; + CopyWindowProcPtr copy_window; + BitmapToRegionProcPtr bitmap_to_region; + TrianglesProcPtr triangles; + AddTrapsProcPtr addtraps; + CreatePictureProcPtr create_picture; + DestroyPictureProcPtr destroy_picture; + UnrealizeGlyphProcPtr unrealize_glyph; +}; +typedef struct glamor_screen_private { + struct glamor_gl_dispatch dispatch; int yInverted; - int screen_fbo; - GLuint vbo, ebo; - int vbo_offset; - int vbo_size; - char *vb; - int vb_stride; enum glamor_gl_flavor gl_flavor; int has_pack_invert; int has_fbo_blit; int max_fbo_size; - /* glamor_finishaccess */ - GLint finish_access_prog[2]; - GLint finish_access_no_revert[2]; - GLint finish_access_swap_rb[2]; - /* glamor_solid */ GLint solid_prog; GLint solid_color_uniform_location; + /* vertext/elment_index buffer object for render */ + GLuint vbo, ebo; + int vbo_offset; + int vbo_size; + char *vb; + int vb_stride; + Bool has_source_coords, has_mask_coords; + int render_nr_verts; + glamor_composite_shader composite_shader[SHADER_SOURCE_COUNT] + [SHADER_MASK_COUNT] + [SHADER_IN_COUNT]; + glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; + Bool glyph_cache_initialized; + + /* shaders to restore a texture to another texture.*/ + GLint finish_access_prog[2]; + GLint finish_access_no_revert[2]; + GLint finish_access_swap_rb[2]; + /* glamor_tile */ GLint tile_prog; @@ -185,19 +195,11 @@ typedef struct glamor_screen_private { 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_pixmap_validate_function_t *pixmap_validate_funcs; - glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; + int screen_fbo; + struct glamor_saved_procs saved_procs; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; - - glamor_glyph_cache_t glyphCaches[GLAMOR_NUM_GLYPH_CACHE_FORMATS]; - Bool glyph_cache_initialized; - struct glamor_gl_dispatch dispatch; + glamor_pixmap_validate_function_t *pixmap_validate_funcs; } glamor_screen_private; typedef enum glamor_access { @@ -236,7 +238,6 @@ typedef union _glamor_pending_op { * @container: The corresponding pixmap's pointer. **/ - typedef struct glamor_pixmap_private { glamor_pixmap_type_t type; unsigned char gl_fbo:1; From 994a9ff7f58161bf5651f83d810eb77b7718ab00 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 18 Jan 2012 17:07:25 +0800 Subject: [PATCH 273/462] glamor_create_picture: Fix the format matching method. We should not simply set a TEXTURE_DRM pixmap to a separated texture pixmap. If the format is compatible with current fbo then it is just fine to keep it as TEXTURE_DRM type and we can safely fallback to DDX layer on it. Signed-off-by: Zhigang Gong --- glamor/glamor_picture.c | 22 ++++++++++++++-------- glamor/glamor_utils.h | 19 ++++++++++++++++--- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index a9e3c267d..6904dab20 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -65,15 +65,21 @@ glamor_create_picture(PicturePtr picture) * the uploading, we need to know the picture format. */ glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); pixmap_priv = glamor_get_pixmap_private(pixmap); + } else { + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { + /* If the picture format is not compatible with glamor fbo format, + * we have to mark this pixmap as a separated texture, and don't + * fallback to DDX layer. */ + if (pixmap_priv->type == GLAMOR_TEXTURE_DRM + && !glamor_pict_format_is_compatible(picture->format, + pixmap->drawable.depth)) + glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); + } } - - if (pixmap_priv) { - pixmap_priv->is_picture = 1; - pixmap_priv->pict_format = picture->format; - /* XXX Some formats are compatible between glamor and ddx driver*/ - if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) - glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE); - } + + pixmap_priv->is_picture = 1; + pixmap_priv->pict_format = picture->format; + return miCreatePicture(picture); } diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 49c7e1de6..491a1ca2e 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -232,18 +232,16 @@ gl_iformat_for_depth(int depth, GLenum * format) case 8: *format = GL_ALPHA; break; -#endif case 24: *format = GL_RGB; break; +#endif default: *format = GL_RGBA; break; } } - - static inline CARD32 format_for_pixmap(PixmapPtr pixmap) { @@ -561,6 +559,21 @@ glamor_get_rgba_from_pixel(CARD32 pixel, return TRUE; } +inline static Bool glamor_pict_format_is_compatible(PictFormatShort pict_format, int depth) +{ + GLenum iformat; + + gl_iformat_for_depth(depth, &iformat); + switch (iformat) { + case GL_RGBA: + return (pict_format == PICT_a8r8g8b8 || pict_format == PICT_x8r8g8b8); + case GL_ALPHA: + return (pict_format == PICT_a8); + default: + return FALSE; + } +} + /* return TRUE if we can access this pixmap at DDX driver. */ inline static Bool glamor_ddx_fallback_check_pixmap(DrawablePtr drawable) { From 15166bba973206dcb98121eb3932660529cfc997 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 18 Jan 2012 17:10:26 +0800 Subject: [PATCH 274/462] Add debug message for all the uploading path. The previous message missed the texture restoring path. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index f43a90b3c..3ed3c5173 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -298,6 +298,13 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, return; need_flip = (flip && !glamor_priv->yInverted); + 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); + /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ if (no_alpha == 0 && no_revert == 1 && !need_flip) { @@ -476,12 +483,6 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) } if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) 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, no_alpha, no_revert, 1); return GLAMOR_UPLOAD_DONE; From ca2ddd33a114fe83584b5fa9f73b7534abdb96fa Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 18 Jan 2012 17:12:32 +0800 Subject: [PATCH 275/462] glamor_set_pixmap_texture/screen_pixmap: Remove useless parameters. As after we got a texture, no matter the texture is created on the glamor_create_pixmap or on the egl layer, we all already know the texture's width and height there. We don't need to pass them in. This commit also simply the glamor_egl_create_textured_screen to reuse the egl_create_textured_pixmap. And also remove the useless root image from the egl private structure. As now the root image is bound to the screen image, we don't take care it separately here. It will be freed at the screen closing. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 38 ++++++++++++++++++------------------- glamor/glamor.h | 11 +++++++---- glamor/glamor_egl.c | 46 ++++++++++++--------------------------------- 3 files changed, 37 insertions(+), 58 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 74c23c6a5..6d7abd543 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -78,17 +78,18 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) pixmap_priv->type = type; } - _X_EXPORT void -glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) +glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL) { pixmap_priv = calloc(sizeof(*pixmap_priv), 1); dixSetPrivate(&pixmap->devPrivates, @@ -117,27 +118,18 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, unsigned int tex) pixmap_priv->gl_tex = 0; } - if (pixmap->devKind == 0) - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, - (((w * - pixmap->drawable. - bitsPerPixel + 7) / 8) + - 3) & ~3, NULL); pixmap->devPrivate.ptr = 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) +glamor_set_screen_pixmap(PixmapPtr screen_pixmap) { - PixmapPtr pixmap = screen->GetScreenPixmap(screen); + ScreenPtr screen = screen_pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv; - glamor_set_pixmap_texture(pixmap, w, h, tex); - pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_priv = glamor_get_screen_private(screen); + pixmap_priv = glamor_get_pixmap_private(screen_pixmap); glamor_priv->screen_fbo = pixmap_priv->fb; } @@ -187,7 +179,13 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); - glamor_set_pixmap_texture(pixmap, w, h, tex); + glamor_set_pixmap_texture(pixmap, tex); + + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + (((w * + pixmap->drawable. + bitsPerPixel + 7) / 8) + + 3) & ~3, NULL); return pixmap; } diff --git a/glamor/glamor.h b/glamor/glamor.h index 1119e374b..51061f31d 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -102,9 +102,12 @@ typedef enum glamor_pixmap_type { */ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); -extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, - int w, int h, - unsigned int tex); + +/* Let glamor to know the screen's fbo. The low level + * driver should already assign a tex + * to this pixmap through the set_pixmap_texture. */ +extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap); + /* @glamor_glyphs_init: Initialize glyphs internal data structures. * * @pScreen: Current screen pointer. @@ -115,7 +118,7 @@ extern _X_EXPORT void glamor_set_screen_pixmap_texture(ScreenPtr screen, */ extern _X_EXPORT Bool glamor_glyphs_init(ScreenPtr pScreen); -extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, int w, int h, +extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex); extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 28a48ca78..1b57b46a8 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -59,10 +59,6 @@ #include #include -#define GLAMOR_VERSION_MAJOR 0 -#define GLAMOR_VERSION_MINOR 1 -#define GLAMOR_VERSION_PATCH 0 - #include "glamor.h" #include "glamor_gl_dispatch.h" @@ -169,40 +165,22 @@ glamor_create_texture_from_image(struct glamor_egl_screen_private return TRUE; } - Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = - glamor_egl_get_screen_private(scrn); - EGLImageKHR image; - GLuint texture; + struct glamor_egl_screen_private *glamor_egl; + PixmapPtr screen_pixmap; - if (!glamor_get_flink_name - (glamor_egl->fd, handle, &glamor_egl->front_buffer_handle)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't flink front buffer handle\n"); + glamor_egl = glamor_egl_get_screen_private(scrn); + screen_pixmap = screen->GetScreenPixmap(screen); + + if (!glamor_egl_create_textured_pixmap(screen_pixmap, handle, stride)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create textured screen."); return FALSE; } - if (glamor_egl->root) { - eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); - glamor_egl->root = EGL_NO_IMAGE_KHR; - } - - image = _glamor_egl_create_image(glamor_egl, - scrn->virtualX, - scrn->virtualY, - stride / 4, - glamor_egl->front_buffer_handle, 32); - if (image == EGL_NO_IMAGE_KHR) - return FALSE; - - glamor_create_texture_from_image(glamor_egl, image, &texture); - glamor_set_screen_pixmap_texture(screen, scrn->virtualX, - scrn->virtualY, texture); - glamor_egl->root = image; + glamor_set_screen_pixmap(screen_pixmap); return TRUE; } @@ -211,12 +189,13 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = - glamor_egl_get_screen_private(scrn); + struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; GLuint texture; int name; + glamor_egl = glamor_egl_get_screen_private(scrn); + if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink pixmap handle\n"); @@ -234,8 +213,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); - glamor_set_pixmap_texture(pixmap, pixmap->drawable.width, - pixmap->drawable.height, texture); + glamor_set_pixmap_texture(pixmap, texture); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); From 2ff41008494e6c5909c058f1f80b4f66617dada1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 18 Jan 2012 19:21:36 +0800 Subject: [PATCH 276/462] glamor_fbo: Introduce glamor fbo to manage all the fb/tex. This is the first patch to implement a fbo/tex pool mechanism which is like the sna's BO cache list. We firstly need to decopule the fbo/tex from each pixmap. The new glamor_pixmap_fbo data structure is for that purpose. It's somehow independent to each pixmap and can be reused latter by other pixmaps once it's detached from the current pixmap. And this commit also slightly change the way to create a memory pixmap. We will not create a pixmap private data structure by default, instead we will crete that structure when a memory pixmap is attaching a fbo to it. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor.c | 111 ++++++++++++++------------------ glamor/glamor_copyarea.c | 12 ++-- glamor/glamor_core.c | 10 +-- glamor/glamor_debug.h | 3 + glamor/glamor_fbo.c | 132 +++++++++++++++++++++++++++++++++++++++ glamor/glamor_pixmap.c | 119 ++++++++++++----------------------- glamor/glamor_priv.h | 58 +++++++++++++---- glamor/glamor_render.c | 24 ++----- glamor/glamor_tile.c | 2 +- glamor/glamor_utils.h | 7 +-- 11 files changed, 290 insertions(+), 189 deletions(-) create mode 100644 glamor/glamor_fbo.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 5c5f7e5dc..d6105d002 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -44,6 +44,7 @@ libglamor_la_SOURCES = \ glamor_picture.c\ glamor_window.c\ glamor_gl_dispatch.c\ + glamor_fbo.c\ glamor.h sdk_HEADERS = glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 6d7abd543..29f827cc4 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -85,52 +85,41 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; glamor_priv = glamor_get_screen_private(screen); dispatch = &glamor_priv->dispatch; pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL) { - pixmap_priv = calloc(sizeof(*pixmap_priv), 1); - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, pixmap_priv); - pixmap_priv->container = pixmap; - pixmap_priv->glamor_priv = glamor_priv; + if (pixmap_priv->fbo) { + fbo = glamor_pixmap_detach_fbo(pixmap_priv); + glamor_destroy_fbo(fbo); } - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); + fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, tex, 0); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - - pixmap_priv->tex = tex; - - /* Create a framebuffer object wrapping the texture so that we can render - * to it. - */ - pixmap_priv->gl_fbo = 1; - if (tex != 0) { - glamor_pixmap_ensure_fb(pixmap); - pixmap_priv->gl_tex = 1; - } else { - pixmap_priv->fb = 0; - pixmap_priv->gl_tex = 0; + if (fbo == NULL) { + ErrorF("XXX fail to create fbo.\n"); + return; } - pixmap->devPrivate.ptr = NULL; + glamor_pixmap_attach_fbo(pixmap, fbo); } void glamor_set_screen_pixmap(PixmapPtr screen_pixmap) { - ScreenPtr screen = screen_pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; - glamor_priv = glamor_get_screen_private(screen); + glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - glamor_priv->screen_fbo = pixmap_priv->fb; + glamor_priv->screen_fbo = pixmap_priv->fbo->fb; + + pixmap_priv->fbo->width = screen_pixmap->drawable.width; + pixmap_priv->fbo->height = screen_pixmap->drawable.height; } PixmapPtr @@ -138,13 +127,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage) { PixmapPtr pixmap; - GLenum format; - GLuint tex; glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_pixmap_fbo *fbo; + int pitch; + int flag; + if (w > 32767 || h > 32767) return NullPixmap; @@ -153,62 +144,53 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, || usage == GLAMOR_CREATE_PIXMAP_CPU) { /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. If we exceed such limitation, we have to use framebuffer. */ - type = GLAMOR_MEMORY; - pixmap = fbCreatePixmap(screen, w, h, depth, usage); + return fbCreatePixmap(screen, w, h, depth, usage); } else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); pixmap_priv = calloc(1, sizeof(*pixmap_priv)); - dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, + + if (!pixmap_priv) + return fbCreatePixmap(screen, w, h, depth, usage); + + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, pixmap_priv); + pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; - pixmap_priv->type = type; - if (w == 0 || h == 0 || type == GLAMOR_MEMORY) + + if (w == 0 || h == 0) return pixmap; - gl_iformat_for_depth(depth, &format); - /* Create the texture used to store the pixmap's data. */ - dispatch->glGenTextures(1, &tex); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, - GL_UNSIGNED_BYTE, NULL); + fbo = glamor_create_fbo(glamor_priv, w, h, depth, 0); - glamor_set_pixmap_texture(pixmap, tex); + if (fbo == NULL) { + fbDestroyPixmap(pixmap); + free(pixmap_priv); + return fbCreatePixmap(screen, w, h, depth, usage); + } - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, - (((w * - pixmap->drawable. - bitsPerPixel + 7) / 8) + - 3) & ~3, NULL); + glamor_pixmap_attach_fbo(pixmap, fbo); + pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); return pixmap; } void glamor_destroy_textured_pixmap(PixmapPtr pixmap) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (pixmap->refcnt == 1) { - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); + glamor_pixmap_private *pixmap_priv; + + pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv != NULL) { - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, - &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, - &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, - &pixmap_priv->pbo); + glamor_pixmap_fbo *fbo; + fbo = glamor_pixmap_detach_fbo(pixmap_priv); + if (fbo) + glamor_destroy_fbo(fbo); free(pixmap_priv); } } @@ -238,6 +220,7 @@ _glamor_block_handler(void *data, OSTimePtr timeout, { glamor_gl_dispatch *dispatch = data; dispatch->glFlush(); + dispatch->glFinish(); } static void diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 4310a0479..a39c97001 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -79,7 +79,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, glamor_validate_pixmap(dst_pixmap); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, - src_pixmap_priv->fb); + src_pixmap_priv->fbo->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, @@ -167,7 +167,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, goto fail; } - if (!src_pixmap_priv->gl_fbo) { + if (!src_pixmap_priv || !src_pixmap_priv->gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); goto fail; @@ -175,6 +175,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, src_status = glamor_upload_pixmap_to_texture(src_pixmap); if (src_status != GLAMOR_UPLOAD_DONE) goto fail; + + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); #endif } else flush_needed = 1; @@ -199,8 +201,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); @@ -216,7 +216,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->tex); + src_pixmap_priv->fbo->tex); #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif @@ -333,7 +333,7 @@ _glamor_copy_n_to_n(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - if (src_pixmap_priv->fb == dst_pixmap_priv->fb) { + if (src_pixmap_priv->fbo && src_pixmap_priv->fbo->fb == dst_pixmap_priv->fbo->fb) { int x_shift = abs(src_x_off - dx - dst_x_off); int y_shift = abs(src_y_off - dy - dst_y_off); for (i = 0; i < nbox; i++) { diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 8ce2104a1..f6f9e832c 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -49,7 +49,7 @@ glamor_get_drawable_location(const DrawablePtr drawable) glamor_get_screen_private(drawable->pScreen); if (pixmap_priv == NULL || pixmap_priv->gl_fbo == 0) return 'm'; - if (pixmap_priv->fb == glamor_priv->screen_fbo) + if (pixmap_priv->fbo->fb == glamor_priv->screen_fbo) return 's'; else return 'f'; @@ -271,13 +271,13 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) glamor_restore_pixmap_to_texture(pixmap); } - if (pixmap_priv->pbo != 0 && pixmap_priv->pbo_valid) { + if (pixmap_priv->fbo->pbo != 0 && pixmap_priv->fbo->pbo_valid) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; + pixmap_priv->fbo->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); + pixmap_priv->fbo->pbo = 0; } else { free(pixmap->devPrivate.ptr); } diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h index b1017490e..ac7e69870 100644 --- a/glamor/glamor_debug.h +++ b/glamor/glamor_debug.h @@ -79,5 +79,8 @@ AbortServer(void) _glamor_priv_->delayed_fallback_string); \ _glamor_priv_->delayed_fallback_pending = 0; } } while(0) +#define DEBUGF(str, ...) +//#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) + #endif diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c new file mode 100644 index 000000000..068d877d7 --- /dev/null +++ b/glamor/glamor_fbo.c @@ -0,0 +1,132 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "glamor_priv.h" + +glamor_pixmap_fbo * +glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, + int w, int h, int depth, GLint tex, int flag) +{ + glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; + GLenum format; + + fbo = calloc(1, sizeof(*fbo)); + if (fbo == NULL) + return NULL; + + gl_iformat_for_depth(depth, &format); + + fbo->tex = tex; + fbo->width = w; + fbo->height = h; + fbo->format = format; + fbo->glamor_priv = glamor_priv; + + glamor_pixmap_ensure_fb(fbo); + + return fbo; +} + +/* Make sure already detached from any pixmap. */ +void +glamor_destroy_fbo(glamor_pixmap_fbo *fbo) +{ + glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + + DEBUGF("Destroy fbo %p tex %d fb %d \n", fbo, fbo->tex, fbo->fb); + if (fbo->fb) + dispatch->glDeleteFramebuffers(1, &fbo->fb); + if (fbo->tex) + dispatch->glDeleteTextures(1, &fbo->tex); + if (fbo->pbo) + dispatch->glDeleteBuffers(1, &fbo->pbo); + + free(fbo); +} + +glamor_pixmap_fbo * +glamor_create_fbo(glamor_screen_private *glamor_priv, + int w, int h, int depth, int flag) +{ + glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; + GLenum format; + GLint tex; + + gl_iformat_for_depth(depth, &format); + dispatch = &glamor_priv->dispatch; + dispatch->glGenTextures(1, &tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, + GL_UNSIGNED_BYTE, NULL); + + fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); + DEBUGF("Creat fbo %p tex %d width %d height %d \n", fbo, tex, w, h); + + return fbo; +} + +glamor_pixmap_fbo * +glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) +{ + glamor_pixmap_fbo *fbo; + + if (pixmap_priv == NULL) + return NULL; + + fbo = pixmap_priv->fbo; + if (fbo == NULL) + return NULL; + + pixmap_priv->fbo = NULL; + return fbo; +} + +/* The pixmap must not be attached to another fbo. */ +void +glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) +{ + glamor_pixmap_private *pixmap_priv; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (pixmap_priv == NULL) { + glamor_screen_private *glamor_priv; + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + pixmap_priv = calloc(1, sizeof(*pixmap_priv)); + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, pixmap_priv); + pixmap_priv->container = pixmap; + pixmap_priv->glamor_priv = glamor_priv; + pixmap_priv->type = GLAMOR_MEMORY; + } + + if (pixmap_priv->fbo) + return; + + pixmap_priv->fbo = fbo; + + switch (pixmap_priv->type) { + case GLAMOR_TEXTURE_ONLY: + case GLAMOR_TEXTURE_DRM: + pixmap_priv->gl_fbo = 1; + if (fbo->tex != 0) + pixmap_priv->gl_tex = 1; + else { + /* XXX For the Xephyr only, may be broken now.*/ + pixmap_priv->gl_tex = 0; + } + pixmap->devPrivate.ptr = NULL; + break; + default: + break; + } +} diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 3ed3c5173..7c76496c8 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -89,7 +89,7 @@ void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fbo->fb); #ifndef GLAMOR_GLES2 dispatch->glMatrixMode(GL_PROJECTION); dispatch->glLoadIdentity(); @@ -97,8 +97,8 @@ glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) dispatch->glLoadIdentity(); #endif dispatch->glViewport(0, 0, - pixmap_priv->container->drawable.width, - pixmap_priv->container->drawable.height); + pixmap_priv->fbo->width, + pixmap_priv->fbo->height); } @@ -242,10 +242,10 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } - if (pixmap_priv->pbo && pixmap_priv->pbo_valid) { + if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) { texels = NULL; dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, - pixmap_priv->pbo); + pixmap_priv->fbo->pbo); } else texels = pixmap->devPrivate.ptr; @@ -309,7 +309,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, * to the fbo directly. */ if (no_alpha == 0 && no_revert == 1 && !need_flip) { __glamor_upload_pixmap_to_texture(pixmap, format, type, - pixmap_priv->tex); + pixmap_priv->fbo->tex); return; } @@ -363,19 +363,18 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, } void -glamor_pixmap_ensure_fb(PixmapPtr pixmap) +glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) { int status; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - if (pixmap_priv->fb == 0) - dispatch->glGenFramebuffers(1, &pixmap_priv->fb); - assert(pixmap_priv->tex != 0); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb); + glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + + if (fbo->fb == 0) + dispatch->glGenFramebuffers(1, &fbo->fb); + assert(fbo->tex != 0); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, pixmap_priv->tex, + GL_TEXTURE_2D, fbo->tex, 0); status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -422,11 +421,13 @@ static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) { int need_fbo; - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv; + GLenum format; + glamor_pixmap_fbo *fbo; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); if (!glamor_check_fbo_size (glamor_priv, pixmap->drawable.width, pixmap->drawable.height) @@ -441,28 +442,14 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return 0; - if (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted) - need_fbo = 1; - else - need_fbo = 0; + fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, + 0); + if (fbo == NULL) + return -1; - if (pixmap_priv->tex == 0) - dispatch->glGenTextures(1, &pixmap_priv->tex); - - if (need_fbo) { - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - pixmap->drawable.width, - pixmap->drawable.height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL); - glamor_pixmap_ensure_fb(pixmap); - } + glamor_pixmap_attach_fbo(pixmap, fbo); return 0; } @@ -575,7 +562,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -599,7 +586,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -726,11 +713,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (pixmap_priv->pbo == 0) + if (pixmap_priv->fbo->pbo == 0) dispatch->glGenBuffers(1, - &pixmap_priv->pbo); + &pixmap_priv->fbo->pbo); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->pbo); + pixmap_priv->fbo->pbo); dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, @@ -740,7 +727,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) format, type, 0); data = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access); - pixmap_priv->pbo_valid = TRUE; + pixmap_priv->fbo->pbo_valid = TRUE; if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == @@ -762,11 +749,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) data = malloc(stride * pixmap->drawable.height); assert(data); if (access != GLAMOR_ACCESS_WO) { - if (pixmap_priv->pbo == 0) + if (pixmap_priv->fbo->pbo == 0) dispatch->glGenBuffers(1, - &pixmap_priv->pbo); + &pixmap_priv->fbo->pbo); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->pbo); + pixmap_priv->fbo->pbo); dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, stride * pixmap->drawable.height, @@ -783,9 +770,9 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) y - 1) * stride, stride); dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - pixmap_priv->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->pbo = 0; + pixmap_priv->fbo->pbo_valid = FALSE; + dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); + pixmap_priv->fbo->pbo = 0; } } @@ -798,29 +785,3 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) return TRUE; } - - - -static void -_glamor_destroy_upload_pixmap(PixmapPtr pixmap) -{ - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; - - assert(pixmap_priv->gl_fbo == 0); - if (pixmap_priv->fb) - dispatch->glDeleteFramebuffers(1, &pixmap_priv->fb); - if (pixmap_priv->tex) - dispatch->glDeleteTextures(1, &pixmap_priv->tex); - if (pixmap_priv->pbo) - dispatch->glDeleteBuffers(1, &pixmap_priv->pbo); - pixmap_priv->fb = pixmap_priv->tex = pixmap_priv->pbo = 0; - -} - -void -glamor_destroy_upload_pixmap(PixmapPtr pixmap) -{ - _glamor_destroy_upload_pixmap(pixmap); -} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 90ed6bb40..b4c3b74af 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -59,6 +59,8 @@ #include "glamor_debug.h" +#include + typedef struct glamor_composite_shader { GLuint prog; GLint dest_to_dest_uniform_location; @@ -123,6 +125,7 @@ enum glamor_gl_flavor { }; #define GLAMOR_CREATE_PIXMAP_CPU 0x100 +#define GLAMOR_CREATE_PIXMAP_FIXUP 0x101 #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 @@ -156,6 +159,10 @@ struct glamor_saved_procs { UnrealizeGlyphProcPtr unrealize_glyph; }; +#define CACHE_FORMAT_COUNT 2 +#define CACHE_BUCKET_WCOUNT 16 +#define CACHE_BUCKET_HCOUNT 16 + typedef struct glamor_screen_private { struct glamor_gl_dispatch dispatch; int yInverted; @@ -238,15 +245,25 @@ typedef union _glamor_pending_op { * @container: The corresponding pixmap's pointer. **/ -typedef struct glamor_pixmap_private { - glamor_pixmap_type_t type; - unsigned char gl_fbo:1; - unsigned char gl_tex:1; - unsigned char pbo_valid:1; - unsigned char is_picture:1; +typedef struct glamor_pixmap_fbo { + unsigned char pbo_valid; GLuint tex; GLuint fb; GLuint pbo; + int width; + int height; + GLenum format; + GLenum type; + glamor_screen_private *glamor_priv; +} glamor_pixmap_fbo; + + +typedef struct glamor_pixmap_private { + unsigned char gl_fbo:1; + unsigned char is_picture:1; + unsigned char gl_tex:1; + glamor_pixmap_type_t type; + glamor_pixmap_fbo *fbo; PictFormatShort pict_format; glamor_pending_op pending_op; PixmapPtr container; @@ -311,6 +328,23 @@ PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, Bool glamor_destroy_pixmap(PixmapPtr pixmap); +glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv); +void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo); +glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, + int w, int h, int depth, GLint tex, int flag); +glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, + int w, int h, int depth, int flag); +void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); + +Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); + +Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); + +#define GLAMOR_CACHE_GET_DEFAULT 0 +#define GLAMOR_CACHE_GET_EAXCT_SIZE 1 +#define GLAMOR_CACHE_GET_UPLOAD 2 + + /* glamor_copyarea.c */ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, @@ -503,14 +537,14 @@ Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, **/ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap); /** - * Ensure to have a fbo attached to the pixmap. - * If the pixmap already has one fbo then do nothing. - * Otherwise, it will generate a new fbo, and bind - * the pixmap's texture to the fbo. - * The pixmap must has a valid texture before call this + * Ensure to have a fbo has a valid/complete glfbo. + * If the fbo already has a valid glfbo then do nothing. + * Otherwise, it will generate a new glfbo, and bind + * the fbo's texture to the glfbo. + * The fbo must has a valid texture before call this * API, othersie, it will trigger a assert. */ -void glamor_pixmap_ensure_fb(PixmapPtr pixmap); +void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo); /** * Upload a pixmap to gl texture. Used by dynamic pixmap diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6a7057afb..99b60c660 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -388,7 +388,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; dispatch->glActiveTexture(GL_TEXTURE0 + unit); - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); switch (picture->repeatType) { case RepeatNone: #ifndef GLAMOR_GLES2 @@ -923,18 +923,16 @@ glamor_composite_with_shader(CARD8 op, mask_status = GLAMOR_NONE; } - source_status = glamor_upload_picture_to_texture(source); + source_status = glamor_upload_picture_to_texture(source); if (source_status != GLAMOR_UPLOAD_DONE) { glamor_fallback ("Failed to upload source texture.\n"); goto fail; } } else { - if (source_status == GLAMOR_UPLOAD_PENDING) { - source_status = - glamor_upload_picture_to_texture(source); + source_status = glamor_upload_picture_to_texture(source); if (source_status != GLAMOR_UPLOAD_DONE) { glamor_fallback ("Failed to upload source texture.\n"); @@ -943,9 +941,7 @@ glamor_composite_with_shader(CARD8 op, } if (mask_status == GLAMOR_UPLOAD_PENDING) { - mask_status = - glamor_upload_picture_to_texture(mask); - + mask_status = glamor_upload_picture_to_texture(mask); if (mask_status != GLAMOR_UPLOAD_DONE) { glamor_fallback ("Failed to upload mask texture.\n"); @@ -1208,22 +1204,14 @@ _glamor_composite(CARD8 op, if (source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (!source_pixmap_priv) { - glamor_set_pixmap_type(source_pixmap, GLAMOR_MEMORY); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - } - if (source_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (!mask_pixmap_priv) { - glamor_set_pixmap_type(mask_pixmap, GLAMOR_MEMORY); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - } - if (mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } if ((!source->pDrawable diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index f5a6e759f..9dadf5e47 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -156,7 +156,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->tex); + src_pixmap_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 491a1ca2e..c7d1c2943 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -13,12 +13,11 @@ #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ - do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height; \ + do { \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height; \ } while(0) - #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \ + ((float)xFixedFrac(_val_) / 65536.0)) From c7e79d6acff5abd7a327d5f4d6698ae5d7583834 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 19 Jan 2012 20:47:55 +0800 Subject: [PATCH 277/462] glamor-fbo-pool: Implement fbo cache mechanism. We classify the cache according to the texture's format/width/height. As openGL doesn't allow us to change a texture's format/width/height after the internal texture object is already allocated, we can't just calculate the size and then according ths size to put the fbo to an bucket which is just like SNA does. We can only put the fbo to the corresponding format/width/height bucket. This commit only support the exact size match. The following patch will remove this restriction, just need to handle the repeat/tile case when the size is not exactly match. Should use fls instead of ffs when decide the width/height bucket, thanks for Chris to point this out. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 66 ++++++++--- glamor/glamor.h | 48 +++++--- glamor/glamor_core.c | 33 ++++-- glamor/glamor_egl.c | 7 +- glamor/glamor_fbo.c | 221 +++++++++++++++++++++++++++++++++++- glamor/glamor_fill.c | 26 +++-- glamor/glamor_gl_dispatch.c | 1 + glamor/glamor_gl_dispatch.h | 1 + glamor/glamor_pixmap.c | 10 +- glamor/glamor_priv.h | 33 ++++-- glamor/glamor_putimage.c | 5 + glamor/glamor_render.c | 35 +++++- glamor/glamor_tile.c | 26 +++-- 13 files changed, 425 insertions(+), 87 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 29f827cc4..9b9d82304 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -210,8 +210,10 @@ glamor_block_handler(ScreenPtr screen) glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_priv->tick++; dispatch->glFlush(); dispatch->glFinish(); + glamor_fbo_expire(glamor_priv); } static void @@ -381,6 +383,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); #endif + glamor_init_pixmap_fbo(screen); glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); glamor_init_putimage_shaders(screen); @@ -392,6 +395,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) #else glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; #endif + glamor_priv->flags = flags; return TRUE; @@ -402,26 +406,54 @@ glamor_init(ScreenPtr screen, unsigned int flags) return FALSE; } +static void +glamor_release_screen_priv(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + + glamor_priv = glamor_get_screen_private(screen); +#ifdef RENDER + glamor_fini_composite_shaders(screen); +#endif + glamor_fini_pixmap_fbo(screen); + glamor_fini_solid_shader(screen); + glamor_fini_tile_shader(screen); + glamor_fini_putimage_shaders(screen); + glamor_fini_finish_access_shaders(screen); + glamor_pixmap_fini(screen); + free(glamor_priv); + + dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, + NULL); +} + Bool glamor_close_screen(int idx, ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv; + int flags; + + glamor_priv = glamor_get_screen_private(screen); + flags = glamor_priv->flags; #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif glamor_glyphs_fini(screen); - screen->CloseScreen = glamor_priv->saved_procs.close_screen; - screen->CreateGC = glamor_priv->saved_procs.create_gc; - screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; - screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; - screen->GetSpans = glamor_priv->saved_procs.get_spans; - screen->ChangeWindowAttributes = - glamor_priv->saved_procs.change_window_attributes; - screen->CopyWindow = glamor_priv->saved_procs.copy_window; - screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; + if (flags & GLAMOR_USE_SCREEN) { + + screen->CloseScreen = glamor_priv->saved_procs.close_screen; + screen->CreateGC = glamor_priv->saved_procs.create_gc; + screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; + screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; + screen->GetSpans = glamor_priv->saved_procs.get_spans; + screen->ChangeWindowAttributes = + glamor_priv->saved_procs.change_window_attributes; + screen->CopyWindow = glamor_priv->saved_procs.copy_window; + screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; + } #ifdef RENDER - if (ps) { + if (ps && (flags & GLAMOR_USE_PICTURE_SCREEN)) { + ps->Composite = glamor_priv->saved_procs.composite; ps->Trapezoids = glamor_priv->saved_procs.trapezoids; ps->Glyphs = glamor_priv->saved_procs.glyphs; @@ -429,13 +461,15 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->CreatePicture = glamor_priv->saved_procs.create_picture; } #endif - if (glamor_priv->vb) - free(glamor_priv->vb); - free(glamor_priv); - return screen->CloseScreen(idx, screen); + glamor_release_screen_priv(screen); + if (flags & GLAMOR_USE_SCREEN) + return screen->CloseScreen(idx, screen); + else + return TRUE; } + void glamor_fini(ScreenPtr screen) { diff --git a/glamor/glamor.h b/glamor/glamor.h index 51061f31d..fe1570022 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -42,7 +42,7 @@ #endif /* GLAMOR_H */ /* @GLAMOR_INVERTED_Y_AXIS: - * set 1 means the GL env's origin (0,0) is at top-left. + * set 1 means the GL env's origin (0,0) is at top-left. * EGL/DRM platform is an example need to set this bit. * glx platform's origin is at bottom-left thus need to * clear this bit.*/ @@ -54,7 +54,7 @@ * create/destroy pixmap and handle the gc ops. need to * set this bit. Standalone glamor DDX driver need to set * this bit. - * Otherwise, need to clear this bit, as the intel video + * Otherwise, need to clear this bit, as the intel video * driver with glamor enabled. * */ #define GLAMOR_USE_SCREEN 2 @@ -97,12 +97,24 @@ typedef enum glamor_pixmap_type { * * This function initializes necessary internal data structure * for glamor. And before calling into this function, the OpenGL - * environment should be ready. Should be called before any real - * glamor rendering or texture allocation functions. + * environment should be ready. Should be called before any real + * glamor rendering or texture allocation functions. */ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); +/* This function is used to free the glamor private screen's + * resources. If the DDX driver is not set GLAMOR_USE_SCREEN, + * then, DDX need to call this function at proper stage, if + * it is the xorg DDX driver,then it should be called at free + * screen stage not the close screen stage. The reason is after + * call to this function, the xorg DDX may need to destroy the + * screen pixmap which must be a glamor pixmap and requires + * the internal data structure still exist at that time. + * Otherwise, the glamor internal structure will not be freed.*/ +extern _X_EXPORT Bool glamor_close_screen(int idx, ScreenPtr screen); + + /* Let glamor to know the screen's fbo. The low level * driver should already assign a tex * to this pixmap through the set_pixmap_texture. */ @@ -133,7 +145,7 @@ extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, * @scrn: Current screen info pointer. * @fd: Current drm fd. * - * This function creates and intialize EGL contexts. + * This function creates and intialize EGL contexts. * Should be called from DDX's preInit function. * Return TRUE if success, otherwise return FALSE. * */ @@ -165,7 +177,7 @@ extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, /* * @glamor_egl_create_textured_pixmap: Try to create a textured pixmap from * a BO handle. - * + * * @pixmap: The pixmap need to be processed. * @handle: The BO's handle attached to this pixmap at DDX layer. * @stride: Stride in bytes for this pixmap. @@ -188,24 +200,24 @@ extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); extern _X_EXPORT int glamor_create_gc(GCPtr gc); extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable); -/* Glamor rendering/drawing functions with XXX_nf. +/* Glamor rendering/drawing functions with XXX_nf. * nf means no fallback within glamor internal if possible. If glamor * fail to accelerate the operation, glamor will return a false, and the * caller need to implement fallback method. Return a true means the * rendering request get done successfully. */ extern _X_EXPORT Bool glamor_fill_spans_nf(DrawablePtr drawable, GCPtr gc, - int n, DDXPointPtr points, + int n, DDXPointPtr points, int *widths, int sorted); extern _X_EXPORT Bool glamor_poly_fill_rect_nf(DrawablePtr drawable, - GCPtr gc, - int nrect, + GCPtr gc, + int nrect, xRectangle * prect); -extern _X_EXPORT Bool glamor_put_image_nf(DrawablePtr drawable, +extern _X_EXPORT Bool glamor_put_image_nf(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, - int w, int h, int left_pad, + int w, int h, int left_pad, int image_format, char *bits); extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src, @@ -216,7 +228,7 @@ extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, + Bool upsidedown, Pixel bitplane, void *closure); extern _X_EXPORT Bool glamor_composite_nf(CARD8 op, @@ -227,12 +239,12 @@ extern _X_EXPORT Bool glamor_composite_nf(CARD8 op, INT16 y_source, INT16 x_mask, INT16 y_mask, - INT16 x_dest, INT16 y_dest, + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height); extern _X_EXPORT Bool glamor_trapezoids_nf(CARD8 op, PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps); @@ -241,14 +253,14 @@ extern _X_EXPORT Bool glamor_glyphs_nf(CARD8 op, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, - INT16 y_src, int nlist, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs); extern _X_EXPORT Bool glamor_triangles_nf(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, + INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris); @@ -270,7 +282,7 @@ extern _X_EXPORT Bool glamor_get_image_nf(DrawablePtr pDrawable, int x, int y, i unsigned int format, unsigned long planeMask, char *d); extern _X_EXPORT Bool glamor_add_traps_nf(PicturePtr pPicture, - INT16 x_off, + INT16 x_off, INT16 y_off, int ntrap, xTrap * traps); extern _X_EXPORT Bool glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f6f9e832c..395e91276 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -114,9 +114,8 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) void glamor_init_finish_access_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; const char *vs_source = "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" @@ -174,25 +173,23 @@ glamor_init_finish_access_shaders(ScreenPtr screen) GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; GLint sampler_uniform_location; + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; glamor_priv->finish_access_prog[0] = dispatch->glCreateProgram(); glamor_priv->finish_access_prog[1] = dispatch->glCreateProgram(); - vs_prog = - glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); - fs_prog = - glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, fs_source); dispatch->glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); dispatch->glAttachShader(glamor_priv->finish_access_prog[0], fs_prog); - avs_prog = - glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, + avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); - set_alpha_prog = - glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, set_alpha_source); dispatch->glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); @@ -254,6 +251,20 @@ glamor_init_finish_access_shaders(ScreenPtr screen) } +void +glamor_fini_finish_access_shaders(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; + dispatch->glDeleteProgram(glamor_priv->finish_access_prog[0]); + dispatch->glDeleteProgram(glamor_priv->finish_access_prog[1]); +} + + + void glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) { diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 1b57b46a8..3d581d2eb 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -77,7 +77,6 @@ glamor_identify(int flags) struct glamor_egl_screen_private { EGLDisplay display; EGLContext context; - EGLImageKHR root; EGLint major, minor; CreateScreenResourcesProcPtr CreateScreenResources; @@ -250,10 +249,6 @@ glamor_egl_close_screen(ScreenPtr screen) glamor_egl_get_screen_private(scrn); glamor_fini(screen); - eglDestroyImageKHR(glamor_egl->display, glamor_egl->root); - - glamor_egl->root = EGL_NO_IMAGE_KHR; - return TRUE; } @@ -402,6 +397,8 @@ glamor_egl_free_screen(int scrnIndex, int flags) } free(glamor_egl); } + + glamor_close_screen(scrn->scrnIndex, scrn->pScreen); } Bool diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 068d877d7..97ba33c1c 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -6,6 +6,132 @@ #include "glamor_priv.h" +#define GLAMOR_CACHE_EXPIRE_MAX 1000 + +#define GLAMOR_CACHE_DEFAULT 0 +#define GLAMOR_CACHE_EXACT_SIZE 1 + +/* Loop from the tail to the head. */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = __container_of((head)->prev, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.prev, pos, member)) + + +#define list_for_each_entry_safe_reverse(pos, tmp, head, member) \ + for (pos = __container_of((head)->prev, pos, member), \ + tmp = __container_of(pos->member.prev, pos, member); \ + &pos->member != (head); \ + pos = tmp, tmp = __container_of(pos->member.prev, tmp, member)) + +#ifdef __i386__ +static inline unsigned long __fls(unsigned long x) +{ + asm("bsr %1,%0" + : "=r" (x) + : "rm" (x)); + return x; +} +#else +static inline unsigned long __fls(unsigned long x) +{ + int n; + + if (x == 0) return(0); + n = 0; + if (x <= 0x0000FFFF) {n = n +16; x = x <<16;} + if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;} + if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;} + if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;} + if (x <= 0x7FFFFFFF) {n = n + 1;} + return 31 - n; +} +#endif + +inline static int cache_wbucket(int size) +{ + int order = __fls(size / 256); + if (order >= CACHE_BUCKET_WCOUNT) + order = CACHE_BUCKET_WCOUNT - 1; + return order; +} + +inline static int cache_hbucket(int size) +{ + int order = __fls(size / 256); + if (order >= CACHE_BUCKET_HCOUNT) + order = CACHE_BUCKET_HCOUNT - 1; + return order; +} + +inline static int cache_format(GLenum format) +{ + switch (format) { +#if 0 + case GL_ALPHA: + return 1; +#endif + case GL_RGBA: + default: + return 0; + } +} + +glamor_pixmap_fbo * +glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag) +{ + struct list *cache; + glamor_pixmap_fbo *fbo_entry; + int size; + + cache = &glamor_priv->fbo_cache[cache_format(format)] + [cache_wbucket(w)] + [cache_hbucket(h)]; + if (flag != GLAMOR_CACHE_EXACT_SIZE) { + list_for_each_entry(fbo_entry, cache, list) { + if (fbo_entry->width == w && fbo_entry->height == h) { + + DEBUGF("Request w %d h %d \n", w, h); + DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", + fbo_entry, fbo_entry->width, fbo_entry->height, + fbo_entry->fb, fbo_entry->tex); + list_del(&fbo_entry->list); + return fbo_entry; + } + } + } + else { + list_for_each_entry(fbo_entry, cache, list) { + if (fbo_entry->width == w && fbo_entry->height == h) { + + DEBUGF("Request w %d h %d \n", w, h); + DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", + fbo_entry, fbo_entry->width, fbo_entry->height, + fbo_entry->fb, fbo_entry->tex); + list_del(&fbo_entry->list); + return fbo_entry; + } + } + } + + return NULL; +} + +void +glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) +{ + struct list *cache; + + cache = &fbo->glamor_priv->fbo_cache[cache_format(fbo->format)] + [cache_wbucket(fbo->width)] + [cache_hbucket(fbo->height)]; + DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, + fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); + list_add(&fbo->list, cache); + fbo->expire = fbo->glamor_priv->tick + GLAMOR_CACHE_EXPIRE_MAX; +} + glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, int w, int h, int depth, GLint tex, int flag) @@ -18,6 +144,7 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, if (fbo == NULL) return NULL; + list_init(&fbo->list); gl_iformat_for_depth(depth, &format); fbo->tex = tex; @@ -31,13 +158,11 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, return fbo; } -/* Make sure already detached from any pixmap. */ -void -glamor_destroy_fbo(glamor_pixmap_fbo *fbo) +static void +glamor_purge_fbo(glamor_pixmap_fbo *fbo) { glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; - - DEBUGF("Destroy fbo %p tex %d fb %d \n", fbo, fbo->tex, fbo->fb); + DEBUGF("Purge fbo %p tex %d fb %d \n", fbo, fbo->tex, fbo->fb); if (fbo->fb) dispatch->glDeleteFramebuffers(1, &fbo->fb); if (fbo->tex) @@ -48,6 +173,79 @@ glamor_destroy_fbo(glamor_pixmap_fbo *fbo) free(fbo); } +void +glamor_fbo_expire(glamor_screen_private *glamor_priv) +{ + struct list *cache; + glamor_pixmap_fbo *fbo_entry, *tmp; + int i,j,k; + int empty_cache = TRUE; + + for(i = 0; i < CACHE_FORMAT_COUNT; i++) + for(j = 0; j < CACHE_BUCKET_WCOUNT; j++) + for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) { + cache = &glamor_priv->fbo_cache[i][j][k]; + list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + if (GLAMOR_TICK_AFTER(fbo_entry->expire, glamor_priv->tick)) { + empty_cache = FALSE; + break; + } + list_del(&fbo_entry->list); + DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, + fbo_entry->expire, glamor_priv->tick); + glamor_purge_fbo(fbo_entry); + } + } + +} + +void +glamor_init_pixmap_fbo(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + int i,j,k; + + glamor_priv = glamor_get_screen_private(screen); + for(i = 0; i < CACHE_FORMAT_COUNT; i++) + for(j = 0; j < CACHE_BUCKET_WCOUNT; j++) + for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) + { + list_init(&glamor_priv->fbo_cache[i][j][k]); + } +} + +void +glamor_fini_pixmap_fbo(ScreenPtr screen) +{ + struct list *cache; + glamor_screen_private *glamor_priv; + glamor_pixmap_fbo *fbo_entry, *tmp; + int i,j,k; + + glamor_priv = glamor_get_screen_private(screen); + for(i = 0; i < CACHE_FORMAT_COUNT; i++) + for(j = 0; j < CACHE_BUCKET_WCOUNT; j++) + for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) + { + cache = &glamor_priv->fbo_cache[i][j][k]; + list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + list_del(&fbo_entry->list); + glamor_purge_fbo(fbo_entry); + } + + } +} + +void +glamor_destroy_fbo(glamor_pixmap_fbo *fbo) +{ + glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + + list_del(&fbo->list); + glamor_pixmap_fbo_cache_put(fbo); + +} + glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, int depth, int flag) @@ -56,8 +254,19 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo; GLenum format; GLint tex; + int cache_flag; + + if (flag == GLAMOR_CREATE_PIXMAP_FIXUP) + cache_flag = GLAMOR_CACHE_EXACT_SIZE; + else + cache_flag = 0; gl_iformat_for_depth(depth, &format); + fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, + format, GLAMOR_CACHE_EXACT_SIZE); + if (fbo) + return fbo; + dispatch = &glamor_priv->dispatch; dispatch->glGenTextures(1, &tex); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -69,8 +278,8 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, GL_UNSIGNED_BYTE, NULL); fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); - DEBUGF("Creat fbo %p tex %d width %d height %d \n", fbo, tex, w, h); + DEBUGF("Creat new fbo %p tex %d width %d height %d \n", fbo, tex, w, h); return fbo; } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index da8097a10..df97ad018 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -101,9 +101,8 @@ glamor_fill(DrawablePtr drawable, void glamor_init_solid_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; const char *solid_vs = "attribute vec4 v_position;" "void main()\n" "{\n" " gl_Position = v_position;\n" @@ -113,12 +112,12 @@ glamor_init_solid_shader(ScreenPtr screen) "void main()\n" "{\n" " gl_FragColor = color;\n" "}\n"; GLint fs_prog, vs_prog; + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; glamor_priv->solid_prog = dispatch->glCreateProgram(); - vs_prog = - glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs); - fs_prog = - glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - solid_fs); + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs); + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + solid_fs); dispatch->glAttachShader(glamor_priv->solid_prog, vs_prog); dispatch->glAttachShader(glamor_priv->solid_prog, fs_prog); @@ -131,6 +130,17 @@ glamor_init_solid_shader(ScreenPtr screen) "color"); } +void +glamor_fini_solid_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; + dispatch->glDeleteProgram(glamor_priv->solid_prog); +} + Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index f8516b4d9..493c96707 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -61,6 +61,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glUniform4f, get_proc_address); INIT_FUNC(dispatch, glUniform4fv, get_proc_address); INIT_FUNC(dispatch, glCreateProgram, get_proc_address); + INIT_FUNC(dispatch, glDeleteProgram, get_proc_address); INIT_FUNC(dispatch, glCreateShader, get_proc_address); INIT_FUNC(dispatch, glCompileShader, get_proc_address); INIT_FUNC(dispatch, glAttachShader, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index a8a699b5c..024de265a 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -97,6 +97,7 @@ typedef struct glamor_gl_dispatch { void (*glUniform4fv) (GLint location, GLsizei count, const GLfloat * value); GLuint(*glCreateProgram) (void); + GLuint(*glDeleteProgram) (GLuint); GLuint(*glCreateShader) (GLenum type); void (*glCompileShader) (GLuint shader); void (*glAttachShader) (GLuint program, GLuint shader); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 7c76496c8..f001962e7 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -63,11 +63,17 @@ glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { void glamor_pixmap_init(ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv; + + glamor_priv = glamor_get_screen_private(screen); glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; } +void +glamor_pixmap_fini(ScreenPtr screen) +{ +} + void glamor_validate_pixmap(PixmapPtr pixmap) { diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b4c3b74af..31f9c93ca 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -159,18 +159,24 @@ struct glamor_saved_procs { UnrealizeGlyphProcPtr unrealize_glyph; }; -#define CACHE_FORMAT_COUNT 2 -#define CACHE_BUCKET_WCOUNT 16 -#define CACHE_BUCKET_HCOUNT 16 +#define CACHE_FORMAT_COUNT 1 +#define CACHE_BUCKET_WCOUNT 4 +#define CACHE_BUCKET_HCOUNT 4 + +#define GLAMOR_TICK_AFTER(t0, t1) \ + (((int)(t1) - (int)(t0)) < 0) typedef struct glamor_screen_private { struct glamor_gl_dispatch dispatch; int yInverted; + unsigned int tick; enum glamor_gl_flavor gl_flavor; int has_pack_invert; int has_fbo_blit; int max_fbo_size; + struct list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; + /* glamor_solid */ GLint solid_prog; GLint solid_color_uniform_location; @@ -207,6 +213,7 @@ typedef struct glamor_screen_private { char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; glamor_pixmap_validate_function_t *pixmap_validate_funcs; + int flags; } glamor_screen_private; typedef enum glamor_access { @@ -246,6 +253,8 @@ typedef union _glamor_pending_op { **/ typedef struct glamor_pixmap_fbo { + struct list list; + unsigned int expire; unsigned char pbo_valid; GLuint tex; GLuint fb; @@ -321,8 +330,6 @@ extern int glamor_debug_level; /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); -Bool glamor_close_screen(int idx, ScreenPtr screen); - PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage); @@ -336,15 +343,15 @@ glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, int depth, int flag); void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); +void glamor_init_pixmap_fbo(ScreenPtr screen); +void glamor_fini_pixmap_fbo(ScreenPtr screen); Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); +void glamor_fbo_expire(glamor_screen_private *glamor_priv); +void glamor_init_pixmap_fbo(ScreenPtr screen); +void glamor_fini_pixmap_fbo(ScreenPtr screen); Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); -#define GLAMOR_CACHE_GET_DEFAULT 0 -#define GLAMOR_CACHE_GET_EAXCT_SIZE 1 -#define GLAMOR_CACHE_GET_UPLOAD 2 - - /* glamor_copyarea.c */ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, @@ -366,6 +373,7 @@ void glamor_finish_access_window(WindowPtr window); Bool glamor_prepare_access_gc(GCPtr gc); void glamor_finish_access_gc(GCPtr gc); void glamor_init_finish_access_shaders(ScreenPtr screen); +void glamor_fini_finish_access_shaders(ScreenPtr screen); const Bool glamor_get_drawable_location(const DrawablePtr drawable); void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int *x, int *y); @@ -427,6 +435,7 @@ void glamor_fill_spans(DrawablePtr drawable, int n, DDXPointPtr points, int *widths, int sorted); void glamor_init_solid_shader(ScreenPtr screen); +void glamor_fini_solid_shader(ScreenPtr screen); /* glamor_getspans.c */ void @@ -468,6 +477,7 @@ void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits); void glamor_init_putimage_shaders(ScreenPtr screen); +void glamor_fini_putimage_shaders(ScreenPtr screen); /* glamor_render.c */ void glamor_composite(CARD8 op, @@ -484,6 +494,7 @@ void glamor_trapezoids(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps); void glamor_init_composite_shaders(ScreenPtr screen); +void glamor_fini_composite_shaders(ScreenPtr screen); void glamor_composite_glyph_rects(CARD8 op, PicturePtr src, PicturePtr mask, PicturePtr dst, int nrect, @@ -501,6 +512,7 @@ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, unsigned char alu, unsigned long planemask, int tile_x, int tile_y); void glamor_init_tile_shader(ScreenPtr screen); +void glamor_fini_tile_shader(ScreenPtr screen); /* glamor_triangles.c */ void @@ -514,6 +526,7 @@ glamor_triangles(CARD8 op, /* glamor_pixmap.c */ void glamor_pixmap_init(ScreenPtr screen); +void glamor_pixmap_fini(ScreenPtr screen); /** * Download a pixmap's texture to cpu memory. If success, * One copy of current pixmap's texture will be put into diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index f285d957c..26d5cf766 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -239,6 +239,11 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, } #endif +void +glamor_fini_putimage_shaders(ScreenPtr screen) +{ +} + static Bool _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 99b60c660..19ed22e55 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -309,11 +309,12 @@ glamor_init_eb(unsigned short *eb, int vert_cnt) void glamor_init_composite_shaders(ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; unsigned short *eb; + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; dispatch->glGenBuffers(1, &glamor_priv->vbo); dispatch->glGenBuffers(1, &glamor_priv->ebo); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); @@ -326,6 +327,34 @@ glamor_init_composite_shaders(ScreenPtr screen) dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); } + + +void +glamor_fini_composite_shaders(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + glamor_composite_shader *shader; + int i,j,k; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; + dispatch->glDeleteBuffers(1, &glamor_priv->vbo); + dispatch->glDeleteBuffers(1, &glamor_priv->ebo); + + + for(i = 0; i < SHADER_SOURCE_COUNT; i++) + for(j = 0; j < SHADER_MASK_COUNT; j++) + for(k = 0; k < SHADER_IN_COUNT; k++) + { + shader = &glamor_priv->composite_shader[i][j][k]; + if (shader->prog) + dispatch->glDeleteProgram(shader->prog); + } + +} + + static Bool glamor_set_composite_op(ScreenPtr screen, CARD8 op, PicturePtr dest, PicturePtr mask) diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 9dadf5e47..7e0e6acb3 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -39,9 +39,8 @@ void glamor_init_tile_shader(ScreenPtr screen) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; const char *tile_vs = "attribute vec4 v_position;\n" "attribute vec4 v_texcoord0;\n" @@ -60,12 +59,12 @@ glamor_init_tile_shader(ScreenPtr screen) GLint fs_prog, vs_prog; GLint sampler_uniform_location; + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; glamor_priv->tile_prog = dispatch->glCreateProgram(); - vs_prog = - glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs); - fs_prog = - glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - tile_fs); + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs); + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + tile_fs); dispatch->glAttachShader(glamor_priv->tile_prog, vs_prog); dispatch->glAttachShader(glamor_priv->tile_prog, fs_prog); @@ -84,6 +83,17 @@ glamor_init_tile_shader(ScreenPtr screen) dispatch->glUseProgram(0); } +void +glamor_fini_tile_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = &glamor_priv->dispatch; + dispatch->glDeleteProgram(glamor_priv->tile_prog); +} + Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, From 9c6fd931a63fb8a5300014265e4f1cacc746857a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 09:59:44 +0800 Subject: [PATCH 278/462] glamor-fbo-pool: Enable to reuse different size fbo/texture. Fixup three special cases, one is in tile and the other is in composite. Both cases are due to repeat texture issue. Maybe we can refine the shader to recalculate texture coords to support partial texture's repeating. The third is when upload a memory pixmap to texture, as now the texture may not have the exact size as the pixmap, we should not use the full rect coords. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 +- glamor/glamor_fbo.c | 4 +- glamor/glamor_pixmap.c | 105 ++++++++++++++++++++++++++++++++++------- glamor/glamor_priv.h | 4 ++ glamor/glamor_render.c | 34 ++++++++++++- glamor/glamor_tile.c | 11 +++++ 6 files changed, 140 insertions(+), 20 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 9b9d82304..6e843f437 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -164,7 +164,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w == 0 || h == 0) return pixmap; - fbo = glamor_create_fbo(glamor_priv, w, h, depth, 0); + fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage); if (fbo == NULL) { fbDestroyPixmap(pixmap); diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 97ba33c1c..9b6a05ef0 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -90,7 +90,7 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, [cache_hbucket(h)]; if (flag != GLAMOR_CACHE_EXACT_SIZE) { list_for_each_entry(fbo_entry, cache, list) { - if (fbo_entry->width == w && fbo_entry->height == h) { + if (fbo_entry->width >= w && fbo_entry->height >= h) { DEBUGF("Request w %d h %d \n", w, h); DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", @@ -263,7 +263,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, gl_iformat_for_depth(depth, &format); fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, - format, GLAMOR_CACHE_EXACT_SIZE); + format, cache_flag); if (fbo) return fbo; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index f001962e7..2020e2145 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -216,7 +216,7 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) int in_restore = 0; static void __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, GLuint tex) + GLenum type, GLuint tex, int sub) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -255,12 +255,19 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, } else texels = pixmap->devPrivate.ptr; - dispatch->glTexImage2D(GL_TEXTURE_2D, - 0, - iformat, - pixmap->drawable.width, - pixmap->drawable.height, 0, format, type, - texels); + if (sub) + dispatch->glTexSubImage2D(GL_TEXTURE_2D, + 0,0,0, + pixmap->drawable.width, + pixmap->drawable.height, format, type, + texels); + else + dispatch->glTexImage2D(GL_TEXTURE_2D, + 0, + iformat, + pixmap->drawable.width, + pixmap->drawable.height, 0, format, type, + texels); } @@ -280,11 +287,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - static float vertices[8] = { -1, -1, - 1, -1, - 1, 1, - -1, 1 - }; + static float vertices[8]; static float texcoords[8] = { 0, 1, 1, 1, 1, 0, @@ -296,7 +299,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, 0, 1 }; float *ptexcoords; - + float dst_xscale, dst_yscale; GLuint tex; int need_flip; @@ -315,16 +318,23 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, * to the fbo directly. */ if (no_alpha == 0 && no_revert == 1 && !need_flip) { __glamor_upload_pixmap_to_texture(pixmap, format, type, - pixmap_priv->fbo->tex); + pixmap_priv->fbo->tex, 1); return; } - if (need_flip) ptexcoords = texcoords; else ptexcoords = texcoords_inv; + pixmap_priv_get_scale(pixmap_priv, &dst_xscale, &dst_yscale); + glamor_set_normalize_vcoords(dst_xscale, + dst_yscale, + 0, 0, + pixmap->drawable.width, pixmap->drawable.height, + glamor_priv->yInverted, + vertices); + /* Slow path, we need to flip y or wire alpha to 1. */ dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), @@ -338,7 +348,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_set_destination_pixmap_priv_nc(pixmap_priv); dispatch->glGenTextures(1, &tex); - __glamor_upload_pixmap_to_texture(pixmap, format, type, tex); + __glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -791,3 +801,66 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) return TRUE; } + +/* fixup a fbo to the exact size as the pixmap. */ +Bool +glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) +{ + glamor_screen_private *glamor_priv; + glamor_pixmap_fbo *old_fbo; + glamor_pixmap_fbo *new_fbo = NULL; + PixmapPtr scratch = NULL; + glamor_pixmap_private *scratch_priv; + DrawablePtr drawable; + GCPtr gc = NULL; + int ret = FALSE; + + drawable = &pixmap_priv->container->drawable; + + if (pixmap_priv->container->drawable.width == pixmap_priv->fbo->width + && pixmap_priv->container->drawable.height == pixmap_priv->fbo->height) + return TRUE; + + old_fbo = pixmap_priv->fbo; + glamor_priv = pixmap_priv->glamor_priv; + + if (!old_fbo) + return FALSE; + + gc = GetScratchGC(drawable->depth, screen); + if (!gc) + goto fail; + + scratch = glamor_create_pixmap(screen, drawable->width, drawable->height, + drawable->depth, + GLAMOR_CREATE_PIXMAP_FIXUP); + + scratch_priv = glamor_get_pixmap_private(scratch); + + if (!scratch_priv || !scratch_priv->fbo) + goto fail; + + ValidateGC(&scratch->drawable, gc); + glamor_copy_area(drawable, + &scratch->drawable, + gc, 0, 0, + drawable->width, drawable->height, + 0, 0); + old_fbo = glamor_pixmap_detach_fbo(pixmap_priv); + new_fbo = glamor_pixmap_detach_fbo(scratch_priv); + glamor_pixmap_attach_fbo(pixmap_priv->container, new_fbo); + glamor_pixmap_attach_fbo(scratch, old_fbo); + + DEBUGF("old %dx%d type %d\n", + drawable->width, drawable->height, pixmap_priv->type); + DEBUGF("copy tex %d %dx%d to tex %d %dx%d \n", + old_fbo->tex, old_fbo->width, old_fbo->height, new_fbo->tex, new_fbo->width, new_fbo->height); + ret = TRUE; +fail: + if (gc) + FreeScratchGC(gc); + if (scratch) + glamor_destroy_pixmap(scratch); + + return ret; +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 31f9c93ca..66e47c662 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -594,6 +594,10 @@ void glamor_destroy_picture(PicturePtr picture); enum glamor_pixmap_status glamor_upload_picture_to_texture(PicturePtr picture); +/* fixup a fbo to the exact size as the pixmap. */ +Bool +glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); + void glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private * pixmap_priv); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 19ed22e55..03f7e3207 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -342,7 +342,6 @@ glamor_fini_composite_shaders(ScreenPtr screen) dispatch->glDeleteBuffers(1, &glamor_priv->vbo); dispatch->glDeleteBuffers(1, &glamor_priv->ebo); - for(i = 0; i < SHADER_SOURCE_COUNT; i++) for(j = 0; j < SHADER_MASK_COUNT; j++) for(k = 0; k < SHADER_IN_COUNT; k++) @@ -408,6 +407,33 @@ glamor_set_composite_op(ScreenPtr screen, return TRUE; } +static void +glamor_composite_texture_fixup(ScreenPtr screen, + PicturePtr picture, + glamor_pixmap_private * pixmap_priv) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + Bool has_repeat; + int width, height; + + if (picture->repeatType == RepeatNone) + has_repeat = FALSE; + else + has_repeat = TRUE; + + if (has_repeat + && ( (pixmap_priv->container->drawable.width != pixmap_priv->fbo->width) + || (pixmap_priv->container->drawable.height != pixmap_priv->fbo->height))) { + /* Currently, we can't support repeat on partial texture, now redirect it + * to an exact size fbo. */ + DEBUGF("prepare to fixup texture \n"); + if (!glamor_fixup_pixmap_priv(screen, pixmap_priv)) + ErrorF("Failed to fixup a unmatch size of repeat picture. \n"); + } +} + static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, @@ -979,6 +1005,12 @@ glamor_composite_with_shader(CARD8 op, } } #endif + + if (key.source != SHADER_SOURCE_SOLID) + glamor_composite_texture_fixup(screen, source, source_pixmap_priv); + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) + glamor_composite_texture_fixup(screen, mask, mask_pixmap_priv); + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); glamor_validate_pixmap(dest_pixmap); if (!glamor_set_composite_op(screen, op, dest, mask)) { diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 7e0e6acb3..4ff4fa15f 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -127,8 +127,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) || ((tile_y != 0) && (tile_y + height > tile->drawable.height))) { + /* XXX We can recreate a new pixmap here to avoid partial tiling. */ goto fail; } + if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; @@ -148,6 +150,15 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; } + + if (src_pixmap_priv->fbo->width != tile->drawable.width + || src_pixmap_priv->fbo->height != tile->drawable.height) { + if (!glamor_fixup_pixmap_priv(screen, src_pixmap_priv)) { + glamor_fallback("Failed to create a fixup pixmap for partial tiling. \n"); + goto fail; + } + } + if (alu != GXcopy) { glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); glamor_validate_pixmap(tile); From 62e536535168827be76dafb1f5b5e0807c1d5ec9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 10:04:21 +0800 Subject: [PATCH 279/462] glamor_composite: Fix one bug when we have too more vertices. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 03f7e3207..eb4d9166c 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1072,7 +1072,7 @@ glamor_composite_with_shader(CARD8 op, } nrect_max = (vert_stride * nrect) > GLAMOR_COMPOSITE_VBO_VERT_CNT ? - (GLAMOR_COMPOSITE_VBO_VERT_CNT / 6) : nrect; + (GLAMOR_COMPOSITE_VBO_VERT_CNT / vert_stride) : nrect; while(nrect) { int mrect, rect_processed; From c244969b331e08679be9a9618d75fe5ee9cc9d86 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 10:55:16 +0800 Subject: [PATCH 280/462] glamor_init: Should set gl_flavor before sub-module intialization. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 6e843f437..51d04cde3 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -318,6 +318,12 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_set_debug_level(&glamor_debug_level); +#ifdef GLAMOR_GLES2 + glamor_priv->gl_flavor = GLAMOR_GL_ES2; +#else + glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; +#endif + if (flags & GLAMOR_USE_SCREEN) { if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, _glamor_wakeup_handler, @@ -390,11 +396,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_finish_access_shaders(screen); glamor_pixmap_init(screen); -#ifdef GLAMOR_GLES2 - glamor_priv->gl_flavor = GLAMOR_GL_ES2; -#else - glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; -#endif glamor_priv->flags = flags; return TRUE; From 64fef665c9297ddd110b8472943f96b55db120ba Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 10:56:17 +0800 Subject: [PATCH 281/462] glamor_render: Add non-Map/Unmap vertex array for GLES. As some GLES implementations' glMapOES /glUnmapOES is not so efficient, we implement the in memory vertex array for them. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 80 +++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index eb4d9166c..8d6137dea 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -305,30 +305,65 @@ glamor_init_eb(unsigned short *eb, int vert_cnt) } } - void glamor_init_composite_shaders(ScreenPtr screen) { glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; unsigned short *eb; + float *vb; + int eb_size; + int vb_size; glamor_priv = glamor_get_screen_private(screen); dispatch = &glamor_priv->dispatch; dispatch->glGenBuffers(1, &glamor_priv->vbo); dispatch->glGenBuffers(1, &glamor_priv->ebo); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); - dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, - GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2, - NULL, GL_DYNAMIC_DRAW); - eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + + eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2; + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, + eb_size, + NULL, GL_DYNAMIC_DRAW); + eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } + else { + vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2); + if (vb == NULL) { + ErrorF("Failed to allocate vb memory.\n"); + exit(1); + } + eb = malloc(eb_size); + } + + if (eb == NULL) { + ErrorF("fatal error, fail to get eb.\n"); + exit(1); + } glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } else { + dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, + eb_size, + eb, GL_DYNAMIC_DRAW); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2, + NULL, GL_DYNAMIC_DRAW); + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + + free(eb); + glamor_priv->vb = (char*)vb; + } } - - void glamor_fini_composite_shaders(ScreenPtr screen) { @@ -350,7 +385,9 @@ glamor_fini_composite_shaders(ScreenPtr screen) if (shader->prog) dispatch->glDeleteProgram(shader->prog); } - + if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP + && glamor_priv->vb) + free(glamor_priv->vb); } @@ -616,11 +653,12 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) glamor_priv->vb_stride += 2 * sizeof(float); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - dispatch->glBufferData(GL_ARRAY_BUFFER, - n_verts * sizeof(float) * 2, - NULL, GL_DYNAMIC_DRAW); - - glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + dispatch->glBufferData(GL_ARRAY_BUFFER, + n_verts * sizeof(float) * 2, + NULL, GL_DYNAMIC_DRAW); + glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + } dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -689,7 +727,16 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!glamor_priv->render_nr_verts) return; - dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + else { + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } + dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, GL_UNSIGNED_SHORT, NULL); } @@ -1013,6 +1060,7 @@ glamor_composite_with_shader(CARD8 op, glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); glamor_validate_pixmap(dest_pixmap); + if (!glamor_set_composite_op(screen, op, dest, mask)) { goto fail; } From 125f317d90b69fa4d6f98da9badc1946f0a099ec Mon Sep 17 00:00:00 2001 From: Peng Li Date: Fri, 20 Jan 2012 11:52:18 +0800 Subject: [PATCH 282/462] glamor_gl_dispatch: fix the dispatch initialization on GLES2. Some gles2 implementation doesn's support get_proc_address. And we also need to avoid get those missing functions pointers when we are GLES2. Signed-off-by: Peng Li Signed-off-by: Zhigang Gong --- glamor/glamor_gl_dispatch.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index 493c96707..da66380fb 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -1,24 +1,36 @@ #include "glamor_priv.h" +#include #define INIT_FUNC(dst,func_name,get) \ dst->func_name = get(#func_name); \ - if (dst->func_name == NULL) \ - { ErrorF("Failed to get function %s", #func_name); \ - goto fail; } + if (dst->func_name == NULL) { \ + dst->func_name = (void *)dlsym(NULL, #func_name); \ + if (dst->func_name == NULL) { \ + ErrorF("Failed to get function %s\n", #func_name);\ + goto fail; \ + } \ + } \ _X_EXPORT Bool glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, int gl_version, void *(*get_proc_address) (const char *)) { +#ifndef GLAMOR_GLES2 INIT_FUNC(dispatch, glMatrixMode, get_proc_address); INIT_FUNC(dispatch, glLoadIdentity, get_proc_address); - INIT_FUNC(dispatch, glViewport, get_proc_address); INIT_FUNC(dispatch, glRasterPos2i, get_proc_address); + INIT_FUNC(dispatch, glDrawPixels, get_proc_address); + INIT_FUNC(dispatch, glLogicOp, get_proc_address); + INIT_FUNC(dispatch, glMapBuffer, get_proc_address); + INIT_FUNC(dispatch, glMapBufferRange, get_proc_address); + INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); + INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address); +#endif + INIT_FUNC(dispatch, glViewport, get_proc_address); INIT_FUNC(dispatch, glDrawArrays, get_proc_address); INIT_FUNC(dispatch, glDrawElements, get_proc_address); INIT_FUNC(dispatch, glReadPixels, get_proc_address); - INIT_FUNC(dispatch, glDrawPixels, get_proc_address); INIT_FUNC(dispatch, glPixelStorei, get_proc_address); INIT_FUNC(dispatch, glTexParameteri, get_proc_address); INIT_FUNC(dispatch, glTexImage2D, get_proc_address); @@ -34,13 +46,9 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glEnable, get_proc_address); INIT_FUNC(dispatch, glDisable, get_proc_address); INIT_FUNC(dispatch, glBlendFunc, get_proc_address); - INIT_FUNC(dispatch, glLogicOp, get_proc_address); INIT_FUNC(dispatch, glActiveTexture, get_proc_address); INIT_FUNC(dispatch, glGenBuffers, get_proc_address); INIT_FUNC(dispatch, glBufferData, get_proc_address); - INIT_FUNC(dispatch, glMapBuffer, get_proc_address); - INIT_FUNC(dispatch, glMapBufferRange, get_proc_address); - INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); INIT_FUNC(dispatch, glBindBuffer, get_proc_address); INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address); INIT_FUNC(dispatch, glFramebufferTexture2D, get_proc_address); @@ -48,7 +56,6 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glDeleteFramebuffers, get_proc_address); INIT_FUNC(dispatch, glGenFramebuffers, get_proc_address); INIT_FUNC(dispatch, glCheckFramebufferStatus, get_proc_address); - INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address); INIT_FUNC(dispatch, glVertexAttribPointer, get_proc_address); INIT_FUNC(dispatch, glDisableVertexAttribArray, get_proc_address); INIT_FUNC(dispatch, glEnableVertexAttribArray, get_proc_address); From 92671e3ac8cc955379085c143ee8cf8b37e760ec Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 11:58:34 +0800 Subject: [PATCH 283/462] glamor_egl: Don't call eglDestroyImageKHR directly. Some implementation doesn't have it. Signed-off-by: Peng Li Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 3d581d2eb..1b18c4c43 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -87,6 +87,7 @@ struct glamor_egl_screen_private { struct gbm_device *gbm; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; + PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; struct glamor_gl_dispatch *dispatch; }; @@ -235,7 +236,7 @@ glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) * a texture. we must call glFlush to make sure the * operation on that texture has been done.*/ glamor_block_handler(pixmap->drawable.pScreen); - eglDestroyImageKHR(glamor_egl->display, image); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, image); } } glamor_destroy_textured_pixmap(pixmap); @@ -336,6 +337,9 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); + glamor_egl->egl_destroy_image_khr = (PFNEGLDESTROYIMAGEKHRPROC) + eglGetProcAddress("eglDestroyImageKHR"); + glamor_egl->egl_image_target_texture2d_oes = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); From 3373d2c696028a9f2f637430c48b9de1a3776800 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 12:10:06 +0800 Subject: [PATCH 284/462] glamor_egl: Add support for the platform doesn't have gbm. Maybe we should use eglGetDisplayDRM to get display, but current PVR's driver is using eglGetDisplay. Signed-off-by: Peng Li Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 1b18c4c43..c273e8a13 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -46,7 +46,9 @@ #define EGL_EGLEXT_PROTOTYPES #define EGL_DISPLAY_NO_X_MESA +#ifdef GLAMOR_HAS_GBM #include +#endif #if GLAMOR_GLES2 #include @@ -84,7 +86,9 @@ struct glamor_egl_screen_private { int fd; int front_buffer_handle; int cpp; +#ifdef GLAMOR_HAS_GBM struct gbm_device *gbm; +#endif PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; @@ -297,12 +301,16 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl; glamor_egl->fd = fd; +#ifdef GLAMOR_HAS_GBM glamor_egl->gbm = gbm_create_device(glamor_egl->fd); if (glamor_egl->gbm == NULL) { ErrorF("couldn't get display device\n"); return FALSE; } glamor_egl->display = eglGetDisplay(glamor_egl->gbm); +#else + glamor_egl->display = eglGetDisplay((EGLNativeDisplayType)fd); +#endif #ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); From 68789b23e791d81c6987c755a56851961cbb262f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 15:56:25 +0800 Subject: [PATCH 285/462] glamor_gles2: Consolidate gles2 pixmap format readable check to one function. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 3 ++- glamor/glamor_getspans.c | 4 +++- glamor/glamor_pixmap.c | 6 +----- glamor/glamor_utils.h | 6 ++++++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 086ec4b6d..377783cb6 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -78,7 +78,8 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && (glamor_tex_format_is_readable(format) || !no_revert)) { /* XXX prepare whole pixmap is not efficient. */ temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &tex_format, diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index be81fbb9c..92c278fe5 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -66,7 +66,9 @@ _glamor_get_spans(DrawablePtr drawable, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && (glamor_tex_format_is_readable(format) || !no_revert)) { + /* XXX prepare whole pixmap is not efficient. */ temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 2020e2145..9c9e517de 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -681,15 +681,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_validate_pixmap(pixmap); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && - ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) - || no_revert != 1)) { - + && (glamor_tex_format_is_readable(format) || !no_revert)) { temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, &type, no_alpha, no_revert); - } switch (access) { case GLAMOR_ACCESS_RO: diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index c7d1c2943..b29292832 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -603,4 +603,10 @@ inline static Bool glamor_ddx_fallback_check_gc(GCPtr gc) return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable)); } +inline static Bool glamor_tex_format_is_readable(GLenum format) +{ + return ((format == GL_RGBA || format == GL_RGB || format == GL_ALPHA)); + +} + #endif From 6fb92e67b3f3dee38d8d440c8ab9f8cc5dcef9bc Mon Sep 17 00:00:00 2001 From: Li Peng Date: Fri, 20 Jan 2012 16:23:17 +0800 Subject: [PATCH 286/462] glamor: check driver support GEM or not glamor calls DRM_IOCTL_GEM_FLINK to get a name for a buffer object. It only works for driver that support GEM, such as intel i915 driver. But for pvr driver who doesn't has GEM, we can't do it this way. According to Chris's comments, we check the has_gem as the following method: Here we just try to flink handle 0. If that fails with ENODEV or ENOTTY instead of ENOENT (or EINVAL on older kernels), set has_gem=0. Signed-off-by: Li Peng Reviewed-by: Zhigang Gong --- glamor/glamor_egl.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index c273e8a13..71121bce7 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -89,6 +89,7 @@ struct glamor_egl_screen_private { #ifdef GLAMOR_HAS_GBM struct gbm_device *gbm; #endif + int has_gem; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; @@ -188,6 +189,19 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) return TRUE; } +Bool +glamor_egl_check_has_gem(int fd) +{ + struct drm_gem_flink flink; + flink.handle = 0; + int err; + + ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + if (errno == ENOENT || err == EINVAL) + return TRUE; + return FALSE; +} + Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { @@ -200,12 +214,16 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) glamor_egl = glamor_egl_get_screen_private(scrn); - if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Couldn't flink pixmap handle\n"); - glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); - exit(1); - } + if (glamor_egl->has_gem) { + if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink pixmap handle\n"); + glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); + exit(1); + } + } else + name = handle; + image = _glamor_egl_create_image(glamor_egl, pixmap->drawable.width, pixmap->drawable.height, @@ -312,6 +330,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) glamor_egl->display = eglGetDisplay((EGLNativeDisplayType)fd); #endif + glamor_egl->has_gem = glamor_egl_check_has_gem(fd); + #ifndef GLAMOR_GLES2 eglBindAPI(EGL_OPENGL_API); #else From 1bfe5957117ba5916236caa021124734228e5aa9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 20:38:29 +0800 Subject: [PATCH 287/462] glamor-pixmap-upload: Create a uploading fbo with a texture only. Just an initial implementation and disabled by default. When uploading a pixmap to a texture, we don't really want to attach the texture to any fbo. So add one fbo type which doesn't has a gl FBO attached to it. This commit can increase the cairo-trace's performance by 10-20%. Now the firefox-planet-gnome is 8.3s. SNA is still the best, only take 3.5s. Thanks for Chris to point out the A1 pixmap uploading bug. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 139 +++++++++++++++++++++++++++++++++-------- glamor/glamor_pixmap.c | 7 ++- glamor/glamor_priv.h | 6 +- 3 files changed, 123 insertions(+), 29 deletions(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 9b6a05ef0..a9399fb3d 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -10,6 +10,7 @@ #define GLAMOR_CACHE_DEFAULT 0 #define GLAMOR_CACHE_EXACT_SIZE 1 +#define GLAMOR_CACHE_TEXTURE 2 /* Loop from the tail to the head. */ #define list_for_each_entry_reverse(pos, head, member) \ @@ -63,7 +64,6 @@ inline static int cache_hbucket(int size) order = CACHE_BUCKET_HCOUNT - 1; return order; } - inline static int cache_format(GLenum format) { switch (format) { @@ -85,10 +85,15 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo_entry; int size; - cache = &glamor_priv->fbo_cache[cache_format(format)] - [cache_wbucket(w)] - [cache_hbucket(h)]; - if (flag != GLAMOR_CACHE_EXACT_SIZE) { + if (!(flag & GLAMOR_CACHE_TEXTURE)) + cache = &glamor_priv->fbo_cache[cache_format(format)] + [cache_wbucket(w)] + [cache_hbucket(h)]; + else + cache = &glamor_priv->tex_cache[cache_format(format)] + [cache_wbucket(w)] + [cache_hbucket(h)]; + if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) { list_for_each_entry(fbo_entry, cache, list) { if (fbo_entry->width >= w && fbo_entry->height >= h) { @@ -118,14 +123,39 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, return NULL; } +static void +glamor_purge_fbo(glamor_pixmap_fbo *fbo) +{ + glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + if (fbo->fb) + dispatch->glDeleteFramebuffers(1, &fbo->fb); + if (fbo->tex) + dispatch->glDeleteTextures(1, &fbo->tex); + if (fbo->pbo) + dispatch->glDeleteBuffers(1, &fbo->pbo); + + free(fbo); +} + + void glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) { struct list *cache; - cache = &fbo->glamor_priv->fbo_cache[cache_format(fbo->format)] - [cache_wbucket(fbo->width)] - [cache_hbucket(fbo->height)]; + if (fbo->fb == 0) { + glamor_purge_fbo(fbo); + return; + } + + if (fbo->fb) + cache = &fbo->glamor_priv->fbo_cache[cache_format(fbo->format)] + [cache_wbucket(fbo->width)] + [cache_hbucket(fbo->height)]; + else + cache = &fbo->glamor_priv->tex_cache[cache_format(fbo->format)] + [cache_wbucket(fbo->width)] + [cache_hbucket(fbo->height)]; DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); list_add(&fbo->list, cache); @@ -153,25 +183,12 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, fbo->format = format; fbo->glamor_priv = glamor_priv; - glamor_pixmap_ensure_fb(fbo); + if (flag != GLAMOR_CREATE_FBO_NO_FBO) + glamor_pixmap_ensure_fb(fbo); return fbo; } -static void -glamor_purge_fbo(glamor_pixmap_fbo *fbo) -{ - glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; - DEBUGF("Purge fbo %p tex %d fb %d \n", fbo, fbo->tex, fbo->fb); - if (fbo->fb) - dispatch->glDeleteFramebuffers(1, &fbo->fb); - if (fbo->tex) - dispatch->glDeleteTextures(1, &fbo->tex); - if (fbo->pbo) - dispatch->glDeleteBuffers(1, &fbo->pbo); - - free(fbo); -} void glamor_fbo_expire(glamor_screen_private *glamor_priv) @@ -195,6 +212,19 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) fbo_entry->expire, glamor_priv->tick); glamor_purge_fbo(fbo_entry); } +#if 0 + cache = &glamor_priv->tex_cache[i][j][k]; + list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + if (GLAMOR_TICK_AFTER(fbo_entry->expire, glamor_priv->tick)) { + empty_cache = FALSE; + break; + } + list_del(&fbo_entry->list); + DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, + fbo_entry->expire, glamor_priv->tick); + glamor_purge_fbo(fbo_entry); + } +#endif } } @@ -211,6 +241,7 @@ glamor_init_pixmap_fbo(ScreenPtr screen) for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) { list_init(&glamor_priv->fbo_cache[i][j][k]); + list_init(&glamor_priv->tex_cache[i][j][k]); } } @@ -232,7 +263,13 @@ glamor_fini_pixmap_fbo(ScreenPtr screen) list_del(&fbo_entry->list); glamor_purge_fbo(fbo_entry); } - +#if 0 + cache = &glamor_priv->tex_cache[i][j][k]; + list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + list_del(&fbo_entry->list); + glamor_purge_fbo(fbo_entry); + } +#endif } } @@ -246,6 +283,54 @@ glamor_destroy_fbo(glamor_pixmap_fbo *fbo) } +glamor_pixmap_fbo * +glamor_create_tex_obj(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag) +{ + glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *fbo; + int cache_flag = GLAMOR_CACHE_TEXTURE; + GLuint tex; + + if (flag == GLAMOR_CREATE_TEXTURE_EXACT_SIZE) + cache_flag |= GLAMOR_CACHE_EXACT_SIZE; + + fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, + format, cache_flag); + if (fbo) + return fbo; + fbo = calloc(1, sizeof(*fbo)); + if (fbo == NULL) + return NULL; + + list_init(&fbo->list); + + dispatch = &glamor_priv->dispatch; + dispatch->glGenTextures(1, &tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, + GL_UNSIGNED_BYTE, NULL); + fbo->tex = tex; + fbo->width = w; + fbo->height = h; + fbo->format = format; + fbo->glamor_priv = glamor_priv; + + return fbo; +} + +void +glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) +{ + assert(tex_obj->fb == 0); + list_del(&tex_obj->list); + glamor_pixmap_fbo_cache_put(tex_obj); +} + glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, int depth, int flag) @@ -256,6 +341,9 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, GLint tex; int cache_flag; + if (flag == GLAMOR_CREATE_FBO_NO_FBO) + goto new_fbo; + if (flag == GLAMOR_CREATE_PIXMAP_FIXUP) cache_flag = GLAMOR_CACHE_EXACT_SIZE; else @@ -266,7 +354,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, format, cache_flag); if (fbo) return fbo; - +new_fbo: dispatch = &glamor_priv->dispatch; dispatch->glGenTextures(1, &tex); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -279,7 +367,6 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); - DEBUGF("Creat new fbo %p tex %d width %d height %d \n", fbo, tex, w, h); return fbo; } diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 9c9e517de..62ca35fc2 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -436,7 +436,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) { - int need_fbo; + int flag = 0; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; GLenum format; @@ -455,13 +455,16 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) return -1; } + if (!(no_alpha || !no_revert || !glamor_priv->yInverted)) + flag = GLAMOR_CREATE_FBO_NO_FBO; + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return 0; fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth, - 0); + flag); if (fbo == NULL) return -1; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 66e47c662..9c2881cbd 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -127,6 +127,10 @@ enum glamor_gl_flavor { #define GLAMOR_CREATE_PIXMAP_CPU 0x100 #define GLAMOR_CREATE_PIXMAP_FIXUP 0x101 +#define GLAMOR_CREATE_FBO_NO_FBO 0x103 + +#define GLAMOR_CREATE_TEXTURE_EXACT_SIZE 0x104 + #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 typedef struct { @@ -176,6 +180,7 @@ typedef struct glamor_screen_private { int max_fbo_size; struct list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; + struct list tex_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; /* glamor_solid */ GLint solid_prog; @@ -251,7 +256,6 @@ typedef union _glamor_pending_op { * #pending_op: currently only support pending filling. * @container: The corresponding pixmap's pointer. **/ - typedef struct glamor_pixmap_fbo { struct list list; unsigned int expire; From a1de528c56ff1cfd05a04c4ad127456ec00707fd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 21 Jan 2012 13:22:14 +0800 Subject: [PATCH 288/462] glamor_create_fbo: Concentrate the fbo size/depth checking. Concentrate checking the size/depth when creating fbo. Simply the pixmap creation and the uploading fbo/texture preparing. Also slightly change the uploading fbo's preparation. If don't need fbo, then a fbo only has valid texture should be enough to return. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 15 +++++---------- glamor/glamor_fbo.c | 4 ++++ glamor/glamor_pixmap.c | 29 +++++++++++++++-------------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 51d04cde3..80434e959 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -139,19 +139,17 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; - if (!glamor_check_fbo_size(glamor_priv, w, h) - || !glamor_check_fbo_depth(depth) - || usage == GLAMOR_CREATE_PIXMAP_CPU) { - /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. - If we exceed such limitation, we have to use framebuffer. */ + if (usage == GLAMOR_CREATE_PIXMAP_CPU || (w == 0 && h == 0)) return fbCreatePixmap(screen, w, h, depth, usage); - } else + else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); pixmap_priv = calloc(1, sizeof(*pixmap_priv)); - if (!pixmap_priv) + if (!pixmap_priv) { + fbDestroyPixmap(pixmap); return fbCreatePixmap(screen, w, h, depth, usage); + } dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, @@ -161,9 +159,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->glamor_priv = glamor_priv; pixmap_priv->type = type; - if (w == 0 || h == 0) - return pixmap; - fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage); if (fbo == NULL) { diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index a9399fb3d..75bdf2ac8 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -341,6 +341,10 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, GLint tex; int cache_flag; + if (!glamor_check_fbo_size(glamor_priv, w, h) + || !glamor_check_fbo_depth(depth)) + return NULL; + if (flag == GLAMOR_CREATE_FBO_NO_FBO) goto new_fbo; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 62ca35fc2..1c810b750 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -436,7 +436,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) { - int flag = 0; + int flag; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; GLenum format; @@ -445,28 +445,29 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - if (!glamor_check_fbo_size - (glamor_priv, pixmap->drawable.width, pixmap->drawable.height) - || !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 (!(no_alpha || !no_revert || !glamor_priv->yInverted)) { - if (!(no_alpha || !no_revert || !glamor_priv->yInverted)) + if (pixmap_priv && pixmap_priv->fbo) + return 0; flag = GLAMOR_CREATE_FBO_NO_FBO; + } else { - if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return 0; + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return 0; + flag = 0; + } fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth, flag); - if (fbo == NULL) + if (fbo == NULL) { + glamor_fallback + ("upload failed, depth %d x %d @depth %d \n", + pixmap->drawable.width, pixmap->drawable.height, + pixmap->drawable.depth); return -1; + } glamor_pixmap_attach_fbo(pixmap, fbo); From 36ac9b7191a4bbbe4fb25ced9ee27d1e91308a15 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 21 Jan 2012 14:41:44 +0800 Subject: [PATCH 289/462] glamor-fbo: Tweek the cache bucket calculation. And also reduce the expire count to 100 which should be good enough on x11perf and cairo-trace testing. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 75bdf2ac8..ffda04ae0 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -6,7 +6,7 @@ #include "glamor_priv.h" -#define GLAMOR_CACHE_EXPIRE_MAX 1000 +#define GLAMOR_CACHE_EXPIRE_MAX 100 #define GLAMOR_CACHE_DEFAULT 0 #define GLAMOR_CACHE_EXACT_SIZE 1 @@ -51,7 +51,7 @@ static inline unsigned long __fls(unsigned long x) inline static int cache_wbucket(int size) { - int order = __fls(size / 256); + int order = __fls(size / 32); if (order >= CACHE_BUCKET_WCOUNT) order = CACHE_BUCKET_WCOUNT - 1; return order; @@ -59,7 +59,7 @@ inline static int cache_wbucket(int size) inline static int cache_hbucket(int size) { - int order = __fls(size / 256); + int order = __fls(size / 32); if (order >= CACHE_BUCKET_HCOUNT) order = CACHE_BUCKET_HCOUNT - 1; return order; From 566cca59e14b223b8dcd045ccc2bbcf08d05b297 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 29 Jan 2012 14:14:36 +0800 Subject: [PATCH 290/462] glamor-gles2: Fixup the pixmap before read back if it is not readable. Signed-off-by: Zhigang Gong --- glamor/glamor_getspans.c | 2 +- glamor/glamor_pixmap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 92c278fe5..6c50d1b5b 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -67,7 +67,7 @@ _glamor_get_spans(DrawablePtr drawable, glamor_validate_pixmap(pixmap); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && (glamor_tex_format_is_readable(format) || !no_revert)) { + && (!glamor_tex_format_is_readable(format) || !no_revert)) { /* XXX prepare whole pixmap is not efficient. */ temp_pixmap = diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 1c810b750..e1542732b 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -685,7 +685,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_validate_pixmap(pixmap); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && (glamor_tex_format_is_readable(format) || !no_revert)) { + && (!glamor_tex_format_is_readable(format) || !no_revert)) { temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, &type, no_alpha, From 864153bb9eeadb539ed5e9488b829c9f3f8b9482 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 27 Jan 2012 13:22:12 +0000 Subject: [PATCH 291/462] Do not reduce a composite to a copy if we need to sample outside of the source In order to maintain Render semantics, samples outside of the source should return CLEAR. The copy routines instead are based on the core protocol and expects the source rectangle to be wholly contained within the drawable and so does no fixup. Fixes the rendering of GTK icons. Signed-off-by: Chris Wilson Reviewed-by: Zhigang Gong --- glamor/glamor_render.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 8d6137dea..1e68e652b 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -602,7 +602,7 @@ glamor_composite_with_copy(CARD8 op, INT16 y_dest, CARD16 width, CARD16 height) { RegionRec region; - int ret; + int ret = FALSE; if (!source->pDrawable) return FALSE; @@ -622,14 +622,27 @@ glamor_composite_with_copy(CARD8 op, x_source, y_source, 0, 0, x_dest, y_dest, width, height)) return TRUE; - ret = TRUE; - if (!glamor_copy_n_to_n_nf(source->pDrawable, - dest->pDrawable, NULL, - REGION_RECTS(®ion), - REGION_NUM_RECTS(®ion), - x_source - x_dest, y_source - y_dest, - FALSE, FALSE, 0, NULL)) - ret = FALSE; + /* Fallback if we sample outside the source so that we swizzle the + * clear color appropriately. If the source has an alpha channel, + * we could rely on CLAMP_TO_BORDER working as required... + */ + if (region.extents.x1 + x_source - x_dest < 0) + goto cleanup_region; + if (region.extents.x2 + x_source - x_dest > source->pDrawable->width) + goto cleanup_region; + + if (region.extents.y1 + y_source - y_dest < 0) + goto cleanup_region; + if (region.extents.y2 + y_source - y_dest > source->pDrawable->height) + goto cleanup_region; + + ret = glamor_copy_n_to_n_nf(source->pDrawable, + dest->pDrawable, NULL, + REGION_RECTS(®ion), + REGION_NUM_RECTS(®ion), + x_source - x_dest, y_source - y_dest, + FALSE, FALSE, 0, NULL); +cleanup_region: REGION_UNINIT(dest->pDrawable->pScreen, ®ion); return ret; } From 97efbd25fed0f86338853d81b974b7f4deb9f1b4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 27 Jan 2012 13:22:13 +0000 Subject: [PATCH 292/462] Use CLAMP_TO_BORDER in copy_n_to_n so we can sample outside of the source In order to reduce a composite operation to a source, we need to provide Render semantics for the pixel values of samples outside of the source pixmap, i.e. they need to be rgba(0, 0, 0, 0). This is provided by using the CLAMP_TO_BORDER repeat mode, but only if the texture has an alpha channel. Signed-off-by: Chris Wilson Reviewed-by: Zhigang Gong --- glamor/glamor_copyarea.c | 6 ++++++ glamor/glamor_render.c | 26 ++++++++++++++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index a39c97001..f2d710a90 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -226,6 +226,12 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_BORDER); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 1e68e652b..789c684c2 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -622,19 +622,21 @@ glamor_composite_with_copy(CARD8 op, x_source, y_source, 0, 0, x_dest, y_dest, width, height)) return TRUE; - /* Fallback if we sample outside the source so that we swizzle the - * clear color appropriately. If the source has an alpha channel, - * we could rely on CLAMP_TO_BORDER working as required... - */ - if (region.extents.x1 + x_source - x_dest < 0) - goto cleanup_region; - if (region.extents.x2 + x_source - x_dest > source->pDrawable->width) - goto cleanup_region; - if (region.extents.y1 + y_source - y_dest < 0) - goto cleanup_region; - if (region.extents.y2 + y_source - y_dest > source->pDrawable->height) - goto cleanup_region; + if (PICT_FORMAT_A(source->format) == 0) { + /* Fallback if we sample outside the source so that we + * swizzle the correct clear color for out-of-bounds texels. + */ + if (region.extents.x1 + x_source - x_dest < 0) + goto cleanup_region; + if (region.extents.x2 + x_source - x_dest > source->pDrawable->width) + goto cleanup_region; + + if (region.extents.y1 + y_source - y_dest < 0) + goto cleanup_region; + if (region.extents.y2 + y_source - y_dest > source->pDrawable->height) + goto cleanup_region; + } ret = glamor_copy_n_to_n_nf(source->pDrawable, dest->pDrawable, NULL, From bf7d79dc0ac2e97ed97e22c1d2c95e77bf959327 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 31 Jan 2012 18:16:58 +0800 Subject: [PATCH 293/462] Refine CloseScreen and FreeScreen processes. This commit move the calling to glamor_close_screen from glamor_egl_free_screen to glamor_egl_close_screen, as this is the right place to do this. We should detach screen fbo and destroy the corresponding KHR image at glamor_egl_close_screen stage. As latter DDX driver will call DestroyPixmap to destroy screen pixmap, if the fbo and image are still there but glamor screen private data pointer has been freed, then it causes segfault. This commit also introduces a new flag GLAMOR_USE_EGL_SCREEN. if DDX driver is using EGL layer then should set this bit when call to glamor_init and then both glamor_close_screen and glamor_egl_close_screen will be registered correctly, DDX layer will not need to call these two functions manually. This way is also the preferred method within Xorg domain. As interfaces changed, bump the version to 0.3.0. Signed-off-by: Zhigang Gong Tested-by: Peng Li --- glamor/glamor.c | 24 ++++++--- glamor/glamor.h | 73 ++++++++++++------------- glamor/glamor_egl.c | 123 +++++++++++++++++++++++++++---------------- glamor/glamor_fbo.c | 2 +- glamor/glamor_priv.h | 1 + 5 files changed, 133 insertions(+), 90 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 80434e959..e900a911b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -318,6 +318,13 @@ glamor_init(ScreenPtr screen, unsigned int flags) #else glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; #endif + /* If we are using egl screen, call egl screen init to + * register correct close screen function. */ + if (flags & GLAMOR_USE_EGL_SCREEN) + glamor_egl_screen_init(screen); + + glamor_priv->saved_procs.close_screen = screen->CloseScreen; + screen->CloseScreen = glamor_close_screen; if (flags & GLAMOR_USE_SCREEN) { if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, @@ -327,9 +334,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) goto fail; } - glamor_priv->saved_procs.close_screen = screen->CloseScreen; - screen->CloseScreen = glamor_close_screen; - glamor_priv->saved_procs.create_gc = screen->CreateGC; screen->CreateGC = glamor_create_gc; @@ -427,6 +431,9 @@ Bool glamor_close_screen(int idx, ScreenPtr screen) { glamor_screen_private *glamor_priv; + PixmapPtr screen_pixmap; + glamor_pixmap_private *screen_pixmap_priv; + glamor_pixmap_fbo *fbo; int flags; glamor_priv = glamor_get_screen_private(screen); @@ -435,9 +442,9 @@ glamor_close_screen(int idx, ScreenPtr screen) PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif glamor_glyphs_fini(screen); + screen->CloseScreen = glamor_priv->saved_procs.close_screen; if (flags & GLAMOR_USE_SCREEN) { - screen->CloseScreen = glamor_priv->saved_procs.close_screen; screen->CreateGC = glamor_priv->saved_procs.create_gc; screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; @@ -457,12 +464,13 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->CreatePicture = glamor_priv->saved_procs.create_picture; } #endif + screen_pixmap = screen->GetScreenPixmap(screen); + screen_pixmap_priv = glamor_get_pixmap_private(screen_pixmap); + fbo = glamor_pixmap_detach_fbo(screen_pixmap_priv); + glamor_purge_fbo(fbo); glamor_release_screen_priv(screen); - if (flags & GLAMOR_USE_SCREEN) - return screen->CloseScreen(idx, screen); - else - return TRUE; + return screen->CloseScreen(idx, screen); } diff --git a/glamor/glamor.h b/glamor/glamor.h index fe1570022..e29a3e43f 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -41,36 +41,6 @@ #endif /* GLAMOR_H */ -/* @GLAMOR_INVERTED_Y_AXIS: - * set 1 means the GL env's origin (0,0) is at top-left. - * EGL/DRM platform is an example need to set this bit. - * glx platform's origin is at bottom-left thus need to - * clear this bit.*/ - -#define GLAMOR_INVERTED_Y_AXIS 1 - -/* @GLAMOR_USE_SCREEN: - * If want to let glamor to do everything including the - * create/destroy pixmap and handle the gc ops. need to - * set this bit. Standalone glamor DDX driver need to set - * this bit. - * Otherwise, need to clear this bit, as the intel video - * driver with glamor enabled. - * */ -#define GLAMOR_USE_SCREEN 2 -/* @GLAMOR_USE_PICTURE_SCREEN: - * If want to let glamor to do all the composition related - * things, need to set this bit. Just as standalone glamor - * DDX driver. - * Otherwise, need to clear this bit, as the intel video - * driver with glamor enabled. - */ -#define GLAMOR_USE_PICTURE_SCREEN 4 - -#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS \ - | GLAMOR_USE_SCREEN \ - | GLAMOR_USE_PICTURE_SCREEN) - /* * glamor_pixmap_type : glamor pixmap's type. * @MEMORY: pixmap is in memory. @@ -90,15 +60,49 @@ typedef enum glamor_pixmap_type { } glamor_pixmap_type_t; #define GLAMOR_EGL_EXTERNAL_BUFFER 3 +#define GLAMOR_INVERTED_Y_AXIS 1 +#define GLAMOR_USE_SCREEN (1 << 1) +#define GLAMOR_USE_PICTURE_SCREEN (1 << 2) +#define GLAMOR_USE_EGL_SCREEN (1 << 3) +#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS \ + | GLAMOR_USE_SCREEN \ + | GLAMOR_USE_PICTURE_SCREEN \ + | GLAMOR_USE_EGL_SCREEN) + /* @glamor_init: Initialize glamor internal data structure. * * @screen: Current screen pointer. * @flags: Please refer the flags description above. * + * @GLAMOR_INVERTED_Y_AXIS: + * set 1 means the GL env's origin (0,0) is at top-left. + * EGL/DRM platform is an example need to set this bit. + * glx platform's origin is at bottom-left thus need to + * clear this bit. + * + * @GLAMOR_USE_SCREEN: + * If running in an pre-existing X environment, and the + * gl context is GLX, then you should set this bit and + * let the glamor to handle all the screen related + * functions such as GC ops and CreatePixmap/DestroyPixmap. + * + * @GLAMOR_USE_PICTURE_SCREEN: + * If don't use any other underlying DDX driver to handle + * the picture related rendering functions, please set this + * bit on. Otherwise, clear this bit. And then it is the DDX + * driver's responsibility to determine how/when to jump to + * glamor's picture compositing path. + * + * @GLAMOR_USE_EGL_SCREEN: + * If you are using EGL layer, then please set this bit + * on, otherwise, clear it. + * * This function initializes necessary internal data structure * for glamor. And before calling into this function, the OpenGL * environment should be ready. Should be called before any real - * glamor rendering or texture allocation functions. + * glamor rendering or texture allocation functions. And should + * be called after the DDX's screen initialization or at the last + * step of the DDX's screen initialization. */ extern _X_EXPORT Bool glamor_init(ScreenPtr screen, unsigned int flags); extern _X_EXPORT void glamor_fini(ScreenPtr screen); @@ -139,6 +143,8 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen); extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage); +extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen); + #ifdef GLAMOR_FOR_XORG /* @glamor_egl_init: Initialize EGL environment. * @@ -173,7 +179,6 @@ extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride); - /* * @glamor_egl_create_textured_pixmap: Try to create a textured pixmap from * a BO handle. @@ -191,10 +196,6 @@ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int stride); extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); - -extern _X_EXPORT Bool glamor_egl_close_screen(ScreenPtr screen); -extern _X_EXPORT void glamor_egl_free_screen(int scrnIndex, int flags); - #endif extern _X_EXPORT int glamor_create_gc(GCPtr gc); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 71121bce7..027722e23 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -84,7 +84,7 @@ struct glamor_egl_screen_private { CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; int fd; - int front_buffer_handle; + EGLImageKHR front_image; int cpp; #ifdef GLAMOR_HAS_GBM struct gbm_device *gbm; @@ -95,6 +95,8 @@ struct glamor_egl_screen_private { PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes; struct glamor_gl_dispatch *dispatch; + CloseScreenProcPtr saved_close_screen; + xf86FreeScreenProc *saved_free_screen; }; int xf86GlamorEGLPrivateIndex = -1; @@ -185,6 +187,8 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) return FALSE; } + glamor_egl->front_image = dixLookupPrivate(&screen_pixmap->devPrivates, + glamor_egl_pixmap_private_key); glamor_set_screen_pixmap(screen_pixmap); return TRUE; } @@ -242,37 +246,51 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) return TRUE; } +static void +_glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) +{ + ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; + EGLImageKHR image; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + + image = dixLookupPrivate(&pixmap->devPrivates, + glamor_egl_pixmap_private_key); + if (image != EGL_NO_IMAGE_KHR && image != NULL) { + /* Before destroy an image which was attached to + * a texture. we must call glFlush to make sure the + * operation on that texture has been done.*/ + glamor_block_handler(pixmap->drawable.pScreen); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, image); + dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, NULL); + } +} + void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) { - EGLImageKHR image; - ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; - struct glamor_egl_screen_private *glamor_egl = - glamor_egl_get_screen_private(scrn); - - if (pixmap->refcnt == 1) { - image = dixLookupPrivate(&pixmap->devPrivates, - glamor_egl_pixmap_private_key); - if (image != EGL_NO_IMAGE_KHR && image != NULL) { - /* Before destroy an image which was attached to - * a texture. we must call glFlush to make sure the - * operation on that texture has been done.*/ - glamor_block_handler(pixmap->drawable.pScreen); - glamor_egl->egl_destroy_image_khr(glamor_egl->display, image); - } - } + if (pixmap->refcnt == 1) + _glamor_egl_destroy_pixmap_image(pixmap); glamor_destroy_textured_pixmap(pixmap); } -Bool -glamor_egl_close_screen(ScreenPtr screen) +static Bool +glamor_egl_close_screen(int idx, ScreenPtr screen) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - struct glamor_egl_screen_private *glamor_egl = - glamor_egl_get_screen_private(scrn); - glamor_fini(screen); + ScrnInfoPtr scrn; + struct glamor_egl_screen_private *glamor_egl; + PixmapPtr screen_pixmap; - return TRUE; + scrn = xf86Screens[screen->myNum]; + glamor_egl = glamor_egl_get_screen_private(scrn); + screen_pixmap = screen->GetScreenPixmap(screen); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, glamor_egl->front_image); + dixSetPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key, NULL); + glamor_egl->front_image = NULL; + + screen->CloseScreen = glamor_egl->saved_close_screen; + + return screen->CloseScreen(idx, screen); } static Bool @@ -299,6 +317,40 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, return FALSE; } +void +glamor_egl_screen_init(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + + glamor_egl->saved_close_screen = screen->CloseScreen; + screen->CloseScreen = glamor_egl_close_screen; +} + +static void +glamor_egl_free_screen(int scrnIndex, int flags) +{ + ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + struct glamor_egl_screen_private *glamor_egl; + + ErrorF("free egl screen resources\n"); + glamor_egl = glamor_egl_get_screen_private(scrn); + if (glamor_egl != NULL) { + + eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); +#ifdef GLAMOR_HAS_GBM + if (glamor_egl->gbm) + gbm_device_destroy(glamor_egl->gbm); +#endif + scrn->FreeScreen = glamor_egl->saved_free_screen; + free(glamor_egl); + scrn->FreeScreen(scrnIndex, flags); + } +} + Bool glamor_egl_init(ScrnInfoPtr scrn, int fd) { @@ -396,6 +448,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) return FALSE; } + glamor_egl->saved_free_screen = scrn->FreeScreen; + scrn->FreeScreen = glamor_egl_free_screen; return TRUE; } @@ -412,27 +466,6 @@ glamor_egl_init_textured_pixmap(ScreenPtr screen) return TRUE; } -void -glamor_egl_free_screen(int scrnIndex, int flags) -{ - ScrnInfoPtr scrn = xf86Screens[scrnIndex]; - struct glamor_egl_screen_private *glamor_egl = - glamor_egl_get_screen_private(scrn); - - if (glamor_egl != NULL) { - if (!(flags & GLAMOR_EGL_EXTERNAL_BUFFER)) { - eglMakeCurrent(glamor_egl->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - - eglTerminate(glamor_egl->display); - } - free(glamor_egl); - } - - glamor_close_screen(scrn->scrnIndex, scrn->pScreen); -} - Bool glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index ffda04ae0..2243564f6 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -123,7 +123,7 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, return NULL; } -static void +void glamor_purge_fbo(glamor_pixmap_fbo *fbo) { glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 9c2881cbd..d8168a52f 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -346,6 +346,7 @@ glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_pri glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, int depth, int flag); void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); +void glamor_purge_fbo(glamor_pixmap_fbo *fbo); void glamor_init_pixmap_fbo(ScreenPtr screen); void glamor_fini_pixmap_fbo(ScreenPtr screen); From 1ab40028740efad1ba2ee16d425b0fbdd822c6ab Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 2 Feb 2012 09:34:42 +0800 Subject: [PATCH 294/462] Don't call dixSetPrivate directly. We may change the way to set/get those private data latter. consolidate to glamor_set_pixmap/screen_private is better than call those dixSetPrivate directly. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 16 +++++----------- glamor/glamor_priv.h | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index e900a911b..0245fdac8 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -70,8 +70,7 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv == NULL) { pixmap_priv = calloc(sizeof(*pixmap_priv), 1); - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, pixmap_priv); + glamor_set_pixmap_private(pixmap, pixmap_priv); pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; } @@ -151,9 +150,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return fbCreatePixmap(screen, w, h, depth, usage); } - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, - pixmap_priv); + glamor_set_pixmap_private(pixmap, pixmap_priv); pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; @@ -269,8 +266,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) goto fail; } - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, - glamor_priv); + glamor_set_screen_private(screen, glamor_priv); if (!dixRegisterPrivateKey (glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) { @@ -401,8 +397,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) fail: free(glamor_priv); - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, - NULL); + glamor_set_screen_private(screen, NULL); return FALSE; } @@ -423,8 +418,7 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_pixmap_fini(screen); free(glamor_priv); - dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, - NULL); + glamor_set_screen_private(screen, NULL); } Bool diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index d8168a52f..0b7558836 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -310,6 +310,16 @@ glamor_get_screen_private(ScreenPtr screen) glamor_screen_private_key); } +static inline void +glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv) +{ + dixSetPrivate(&screen->devPrivates, + glamor_screen_private_key, + priv); +} + + + static inline glamor_pixmap_private * glamor_get_pixmap_private(PixmapPtr pixmap) { @@ -317,6 +327,16 @@ glamor_get_pixmap_private(PixmapPtr pixmap) glamor_pixmap_private_key); } +static inline void +glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) +{ + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, + priv); +} + + + /** * Returns TRUE if the given planemask covers all the significant bits in the From 1817b6c0cf20aa6fc1e1aa5b68e47473f341b85a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 2 Feb 2012 11:21:05 +0800 Subject: [PATCH 295/462] glamor_eglmodule: Change module name according to normalize naming rule. As Xorg module loader will normalize module name which will remove '_' when we put "glamor_egl" to the configure file, then it will fail to find us. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 13 ++++++------- glamor/glamor.h | 3 +++ glamor/glamor_eglmodule.c | 7 ++++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index d6105d002..ca8fc3fbf 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -50,13 +50,12 @@ libglamor_la_SOURCES = \ sdk_HEADERS = glamor.h if EGL -LIBGLAMOR_EGL = libglamor_egl.la -module_LTLIBRARIES = $(LIBGLAMOR_EGL) -libglamor_egl_la_DEPENDENCIES = libglamor.la -libglamor_egl_la_LDFLAGS = -avoid-version -module $(EGL_LIBS) -lglamor -#libglamor_egl_la_LIBADD = $(top_builddir)/src/libglamor.la -libglamor_egl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c -libglamor_egl_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) +LIBGLAMOREGL = libglamoregl.la +module_LTLIBRARIES = $(LIBGLAMOREGL) +libglamoregl_la_DEPENDENCIES = libglamor.la +libglamoregl_la_LDFLAGS = -avoid-version -module $(EGL_LIBS) -lglamor +libglamoregl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c +libglamoregl_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) endif diff --git a/glamor/glamor.h b/glamor/glamor.h index e29a3e43f..3d6e5fe7f 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -146,6 +146,9 @@ extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen); #ifdef GLAMOR_FOR_XORG + +#define GLAMOR_EGL_MODULE_NAME "glamoregl" + /* @glamor_egl_init: Initialize EGL environment. * * @scrn: Current screen info pointer. diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c index 4da57af93..e1f6672af 100644 --- a/glamor/glamor_eglmodule.c +++ b/glamor/glamor_eglmodule.c @@ -29,11 +29,12 @@ #endif #include - +#define GLAMOR_FOR_XORG +#include "glamor.h" #include "xf86Module.h" static XF86ModuleVersionInfo VersRec = { - "glamor_egl", + GLAMOR_EGL_MODULE_NAME, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, @@ -45,4 +46,4 @@ static XF86ModuleVersionInfo VersRec = { {0, 0, 0, 0} /* signature, to be patched into the file by a tool */ }; -_X_EXPORT XF86ModuleData glamor_eglModuleData = { &VersRec, NULL, NULL }; +_X_EXPORT XF86ModuleData glamoreglModuleData = { &VersRec, NULL, NULL }; From 39d9e6c693a4c3ad12c6569f1fd56e0a87b164d2 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 3 Feb 2012 11:21:37 +0800 Subject: [PATCH 296/462] prepare_access: Don't use fbo after it was downloaded. We add a new gl_fbo status GLAMOR_FBO_DOWNLOADED to indicate the fbo was already downloaded to CPU. Then latter the access to this pixmap will be treated as pure CPU access. In glamor, if we fallback to DDX/fbXXX, then we fallback everything currently. We don't support to jump into glamor acceleration layer between a prepare_access/finish_access. Actually, fbCopyPlane is such a function which may call to acceleration function within it. Then we must mark the downloaded pixmap to another state rather than a normal fbo textured pixmap, and then stick to use it as a in-memory pixmap. Signed-off-by: Zhigang Gong Tested-by: Peng Li --- glamor/glamor_core.c | 7 ++++--- glamor/glamor_pixmap.c | 3 ++- glamor/glamor_priv.h | 39 ++++++++++++++++++++++++++++----------- glamor/glamor_utils.h | 3 ++- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 395e91276..01c9aeaf9 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -263,8 +263,6 @@ glamor_fini_finish_access_shaders(ScreenPtr screen) dispatch->glDeleteProgram(glamor_priv->finish_access_prog[1]); } - - void glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) { @@ -275,7 +273,7 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) glamor_get_screen_private(drawable->pScreen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv)) return; if (access_mode != GLAMOR_ACCESS_RO) { @@ -293,6 +291,9 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) free(pixmap->devPrivate.ptr); } + if (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED) + pixmap_priv->gl_fbo = GLAMOR_FBO_NORMAL; + pixmap->devPrivate.ptr = NULL; } diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index e1542732b..6563e949b 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -641,7 +641,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, * 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) { @@ -794,6 +793,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); done: + + pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; pixmap->devPrivate.ptr = data; if (temp_pixmap) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0b7558836..b19a30402 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -243,19 +243,23 @@ typedef union _glamor_pending_op { glamor_pending_fill fill; } glamor_pending_op; -/* - * 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. +#define GLAMOR_FBO_NORMAL 1 +#define GLAMOR_FBO_DOWNLOADED 2 +/* glamor_pixmap_fbo: + * @list: to be used to link to the cache pool list. + * @expire: when push to cache pool list, set a expire count. + * will be freed when glamor_priv->tick is equal or + * larger than this expire count in block handler. * @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. - * @pict_format: the corresponding picture's format. - * #pending_op: currently only support pending filling. - * @container: The corresponding pixmap's pointer. - **/ + * @width: width of this fbo. + * @height: height of this fbo. + * @format: internal format of this fbo's texture. + * @type: internal type of this fbo's texture. + * @glamor_priv: point to glamor private data. + */ typedef struct glamor_pixmap_fbo { struct list list; unsigned int expire; @@ -270,9 +274,22 @@ typedef struct glamor_pixmap_fbo { glamor_screen_private *glamor_priv; } glamor_pixmap_fbo; - +/* + * glamor_pixmap_private - glamor pixmap's private structure. + * @gl_fbo: + * 0 - The pixmap doesn't has a fbo attached to it. + * GLAMOR_FBO_NORMAL - The pixmap has a fbo and can be accessed normally. + * GLAMOR_FBO_DOWNLOADED - The pixmap has a fbo and already downloaded to + * CPU, so it can only be treated as a in-memory pixmap + * if this bit is set. + * @gl_tex: The pixmap is in a gl texture originally. + * @is_picture: The drawable is attached to a picture. + * @pict_format: the corresponding picture's format. + * #pending_op: currently only support pending filling. + * @container: The corresponding pixmap's pointer. + **/ typedef struct glamor_pixmap_private { - unsigned char gl_fbo:1; + unsigned char gl_fbo:2; unsigned char is_picture:1; unsigned char gl_tex:1; glamor_pixmap_type_t type; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index b29292832..a60b146c1 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -175,7 +175,8 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) #define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1) -#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == 1) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED)) #define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ From 91891b3711b1fe1402bb7742c20e976fab63c6fe Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 3 Feb 2012 11:44:51 +0800 Subject: [PATCH 297/462] glamor_fill/tile: Fixed a tileX/tileY calculation bug. The previous's calculation is incorrect, now fix it and then we don't need to fallback at glamor_tile. Signed-off-by: Zhigang Gong Tested-by: Peng Li --- glamor/glamor_fill.c | 5 ++--- glamor/glamor_tile.c | 7 ------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index df97ad018..b462f5922 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -31,7 +31,6 @@ * * GC fill implementation, based loosely on fb_fill.c */ - Bool glamor_fill(DrawablePtr drawable, GCPtr gc, int x, int y, int width, int height, Bool fallback) @@ -74,8 +73,8 @@ glamor_fill(DrawablePtr drawable, height, gc->alu, gc->planemask, - drawable->x + x + off_x - gc->patOrg.x, - drawable->y + y + off_y - gc->patOrg.y)) + x - drawable->x - gc->patOrg.x, + y - drawable->y - gc->patOrg.y)) goto fail; break; } diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 4ff4fa15f..3087bea6e 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -124,13 +124,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL) goto fail; - if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) - || ((tile_y != 0) - && (tile_y + height > tile->drawable.height))) { - /* XXX We can recreate a new pixmap here to avoid partial tiling. */ - goto fail; - } - if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; From bf24c2c06870dc38b21795f4f6fc51b053134181 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 3 Feb 2012 11:46:01 +0800 Subject: [PATCH 298/462] glamor_dump_pixmap: Add helper routine to dump pixmap. For debug purpose only to dump the pixmap's content. As this function will call glamor_prepare_access/glamor_finish_access internally. Please use it carefully. Signed-off-by: Zhigang Gong --- glamor/glamor_utils.h | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index a60b146c1..74ce6cd0f 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -610,4 +610,57 @@ inline static Bool glamor_tex_format_is_readable(GLenum format) } +static inline void _glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int w, int h) +{ + int i,j; + unsigned char * p = pixmap->devPrivate.ptr; + int stride = pixmap->devKind; + + p = p + y * stride + x; + ErrorF("devKind %d, x %d y %d w %d h %d width %d height %d\n", stride, x, y, w, h, pixmap->drawable.width, pixmap->drawable.height); + + for (i = 0; i < h; i++) + { + ErrorF("line %3d: ", i); + for(j = 0; j < w; j++) + ErrorF("%2x ", p[j]); + p += stride; + ErrorF("\n"); + } +} + +static inline void _glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h) +{ + int i,j; + unsigned int * p = pixmap->devPrivate.ptr; + int stride = pixmap->devKind / 4; + + p = p + y * stride + x; + + for (i = 0; i < h; i++) + { + ErrorF("line %3d: ", i); + for(j = 0; j < w; j++) + ErrorF("%2x ", p[j]); + p += stride; + ErrorF("\n"); + } +} + +static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h) +{ + glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO); + switch (pixmap->drawable.depth) { + case 8: + _glamor_dump_pixmap_byte(pixmap, x, y, w, h); + break; + case 24: + case 32: + _glamor_dump_pixmap_word(pixmap, x, y, w, h); + break; + default: + assert(0); + } + glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); +} #endif From e03ad27dfb885e58298e1fd2accac0b6ad409fce Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 11 Feb 2012 07:37:17 +0800 Subject: [PATCH 299/462] glamor_picture: Fix the wrong order of header file. Signed-off-by: Zhigang Gong --- glamor/glamor_picture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 6904dab20..217fd4048 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -4,8 +4,8 @@ #include -#include "mipict.h" #include "glamor_priv.h" +#include "mipict.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. From 0a8fb8563f3cecf2019d3a35d5a61ec2b3a069cd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Feb 2012 15:34:43 +0800 Subject: [PATCH 300/462] glamor_pixmap: Should bind unpack buffer to 0 after the uploading. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 6563e949b..1a63ffdd1 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -268,6 +268,9 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, pixmap->drawable.width, pixmap->drawable.height, 0, format, type, texels); + + if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) + dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } From 430bc16ca03b3ea00255a4045c8e9fd11aea95ad Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Feb 2012 16:04:07 +0800 Subject: [PATCH 301/462] GLX: Enable glx support. If we are using MESA as our GL library, then both xserver's GLX and glamor are link to the same library. As xserver's GLX has its own _glapi_get/set_context/dispatch etc, and it is a simplified version derived from mesa thus is not sufficient for mesa/egl's dri loader which is used by glamor. Then if glx module is loaded before glamoregl module, the initialization of mesa/egl/opengl will not be correct, and will fail at a very early stage, most likely fail to map the element buffer. Two methodis to fix this problem, first is to modify the xserver's glx's glapi.c to fit mesa's requirement. The second is to put a glamor.conf as below, to the system's xorg.conf path. Section "Module" Load "glamoregl" EndSection Then glamor will be loaded firstly, and the mesa's libglapi.so will be used. As current xserver's dispatch table is the same as mesa's, then the glx's dri loader can work without problem. We took the second method as it don't need any change to xorg.:) Although this is not a graceful implementation as it depends on the xserver's dispatch table and the mesa's dispatch table is the same and the context set and get is using the same method. Anyway it works. As by default, xserver will enable GLX_USE_TLS. But mesa will not enable it, you may need to enable that when build mesa. Three pre-requirements to make this glamor version work: 0. Make sure xserver has commit 66e603, if not please pull the latest master branch. 1. Rebuild mesa by enable GLX_USE_TLS. 2. Put the glamor.conf to your system's xorg.conf path and make sure it loaded prior to glx module. Preliminary testing shows indirect glxgears works fine. If user want to use GLES2 for glamor by using MESA, GLX will not work correctly. If you are not using normal MESA, for example PVR's private GLES implementation, then it should be ok to use GLES2 glamor and the GLX should work as expected. In this commit, I use gbm to check whether we are using MESA or non-mesa. Maybe not the best way. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 4 +- glamor/glamor.c | 8 +-- glamor/glamor.h | 4 ++ glamor/glamor_copyarea.c | 15 +++-- glamor/glamor_copyplane.c | 7 ++ glamor/glamor_egl.c | 59 +++++++++++++++-- glamor/glamor_fbo.c | 14 +++- glamor/glamor_fillspans.c | 22 +++++-- glamor/glamor_getimage.c | 14 +++- glamor/glamor_getspans.c | 15 +++-- glamor/glamor_glyphblt.c | 21 ++++++ glamor/glamor_polyfillrect.c | 21 ++++-- glamor/glamor_polylines.c | 6 ++ glamor/glamor_polyops.c | 21 ++++++ glamor/glamor_priv.h | 1 + glamor/glamor_putimage.c | 20 ++++-- glamor/glamor_render.c | 22 +++++-- glamor/glamor_setspans.c | 18 ++++-- glamor/glamor_utils.h | 29 +++++++++ glamor/glapi.h | 121 +++++++++++++++++++++++++++++++++++ 20 files changed, 391 insertions(+), 51 deletions(-) create mode 100644 glamor/glapi.h diff --git a/glamor/Makefile.am b/glamor/Makefile.am index ca8fc3fbf..c7e300096 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -53,9 +53,9 @@ if EGL LIBGLAMOREGL = libglamoregl.la module_LTLIBRARIES = $(LIBGLAMOREGL) libglamoregl_la_DEPENDENCIES = libglamor.la -libglamoregl_la_LDFLAGS = -avoid-version -module $(EGL_LIBS) -lglamor +libglamoregl_la_LDFLAGS = -avoid-version -module $(EGL_LIBS) -lglamor $(GLX_SYS_LIBS) libglamoregl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c -libglamoregl_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) +libglamoregl_la_CFLAGS = $(AM_CFLAGS) $(GLX_DEFINES) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) endif diff --git a/glamor/glamor.c b/glamor/glamor.c index 0245fdac8..6b6330f4c 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -83,11 +83,9 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) ScreenPtr screen = pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; glamor_pixmap_fbo *fbo; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv->fbo) { @@ -130,7 +128,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; glamor_pixmap_fbo *fbo; int pitch; int flag; @@ -149,7 +146,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, fbDestroyPixmap(pixmap); return fbCreatePixmap(screen, w, h, depth, usage); } - glamor_set_pixmap_private(pixmap, pixmap_priv); pixmap_priv->container = pixmap; @@ -201,11 +197,14 @@ glamor_block_handler(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + GLAMOR_DEFINE_CONTEXT; + GLAMOR_SET_CONTEXT(glamor_priv); glamor_priv->tick++; dispatch->glFlush(); dispatch->glFinish(); glamor_fbo_expire(glamor_priv); + GLAMOR_RESTORE_CONTEXT(glamor_priv); } static void @@ -392,6 +391,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_pixmap_init(screen); glamor_priv->flags = flags; + glamor_priv->screen = screen; return TRUE; diff --git a/glamor/glamor.h b/glamor/glamor.h index 3d6e5fe7f..712a7a9b2 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -145,6 +145,10 @@ extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen); +extern _X_EXPORT void * glamor_egl_make_current(ScreenPtr screen); + +extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen, void *context); + #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index f2d710a90..e6569343e 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -308,6 +308,7 @@ _glamor_copy_n_to_n(DrawablePtr src, PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; DrawablePtr temp_src = src; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; + glamor_screen_private *glamor_priv; BoxRec bound; ScreenPtr screen; int temp_dx = dx; @@ -315,7 +316,8 @@ _glamor_copy_n_to_n(DrawablePtr src, int src_x_off, src_y_off, dst_x_off, dst_y_off; int i; int overlaped = 0; - Bool ret = TRUE; + Bool ret = FALSE; + GLAMOR_DEFINE_CONTEXT; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); @@ -323,6 +325,9 @@ _glamor_copy_n_to_n(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; + glamor_priv = glamor_get_screen_private(dst->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); @@ -356,6 +361,7 @@ _glamor_copy_n_to_n(DrawablePtr src, || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { + ret = TRUE; goto done; } #endif @@ -400,6 +406,7 @@ _glamor_copy_n_to_n(DrawablePtr src, if (glamor_copy_n_to_n_textured (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { + ret = TRUE; goto done; } @@ -408,10 +415,8 @@ _glamor_copy_n_to_n(DrawablePtr src, if (!fallback && glamor_ddx_fallback_check_pixmap(src) - && glamor_ddx_fallback_check_pixmap(dst)) { - ret = FALSE; + && glamor_ddx_fallback_check_pixmap(dst)) goto done; - } glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); @@ -436,12 +441,14 @@ _glamor_copy_n_to_n(DrawablePtr src, } glamor_finish_access(dst, GLAMOR_ACCESS_RW); } + ret = TRUE; done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); if (temp_src != src) glamor_destroy_pixmap(temp_pixmap); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c index 288d7eddc..b6b26a50c 100644 --- a/glamor/glamor_copyplane.c +++ b/glamor/glamor_copyplane.c @@ -37,17 +37,24 @@ _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane, RegionPtr *pRegion, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pSrc) && glamor_ddx_fallback_check_pixmap(pDst)) goto fail; + + glamor_priv = glamor_get_screen_private(pDst->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDst, GLAMOR_ACCESS_RW); glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO); *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); glamor_finish_access(pSrc, GLAMOR_ACCESS_RO); glamor_finish_access(pDst, GLAMOR_ACCESS_RW); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 027722e23..a339527d8 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -63,6 +63,9 @@ #include "glamor.h" #include "glamor_gl_dispatch.h" +#ifdef GLX_USE_SHARED_DISPATCH +#include "glapi.h" +#endif static const char glamor_name[] = "glamor"; @@ -90,6 +93,7 @@ struct glamor_egl_screen_private { struct gbm_device *gbm; #endif int has_gem; + void *gl_context; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; @@ -101,13 +105,46 @@ struct glamor_egl_screen_private { int xf86GlamorEGLPrivateIndex = -1; -static struct glamor_egl_screen_private -* +static struct glamor_egl_screen_private * glamor_egl_get_screen_private(ScrnInfoPtr scrn) { return (struct glamor_egl_screen_private *) scrn->privates[xf86GlamorEGLPrivateIndex].ptr; } +#ifdef GLX_USE_SHARED_DISPATCH +_X_EXPORT void * +glamor_egl_make_current(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + GET_CURRENT_CONTEXT(current); + + if (glamor_egl->gl_context != current) { + eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, + glamor_egl->context)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make EGL context current\n"); + return NULL; + } + return current; + } + return NULL; +} + +_X_EXPORT void +glamor_egl_restore_context(ScreenPtr screen, void *context) +{ + if (context) + SET_CURRENT_CONTEXT(context); +} +#else +#define glamor_egl_make_current(x) NULL +#define glamor_egl_restore_context(s, c) +#endif static EGLImageKHR _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl, @@ -215,9 +252,12 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) EGLImageKHR image; GLuint texture; int name; + void *prev_context; + Bool ret = FALSE; glamor_egl = glamor_egl_get_screen_private(scrn); + prev_context = glamor_egl_make_current(screen); if (glamor_egl->has_gem) { if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, @@ -234,16 +274,20 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) ((stride * 8 + 7) / pixmap->drawable.bitsPerPixel), name, pixmap->drawable.depth); - if (image == EGL_NO_IMAGE_KHR) - return FALSE; + if (image == EGL_NO_IMAGE_KHR) + goto done; glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, texture); dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image); + ret = TRUE; - return TRUE; +done: + if (prev_context) + glamor_egl_restore_context(screen, prev_context); + return ret; } static void @@ -447,7 +491,10 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) "Failed to make EGL context current\n"); return FALSE; } - +#ifdef GLX_USE_SHARED_DISPATCH + GET_CURRENT_CONTEXT(current); + glamor_egl->gl_context = current; +#endif glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; return TRUE; diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 2243564f6..929cababa 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -126,6 +126,9 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, void glamor_purge_fbo(glamor_pixmap_fbo *fbo) { + GLAMOR_DEFINE_CONTEXT; + + GLAMOR_SET_CONTEXT(fbo->glamor_priv); glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; if (fbo->fb) dispatch->glDeleteFramebuffers(1, &fbo->fb); @@ -133,6 +136,7 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo) dispatch->glDeleteTextures(1, &fbo->tex); if (fbo->pbo) dispatch->glDeleteBuffers(1, &fbo->pbo); + GLAMOR_RESTORE_CONTEXT(fbo->glamor_priv); free(fbo); } @@ -166,7 +170,6 @@ glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, int w, int h, int depth, GLint tex, int flag) { - glamor_gl_dispatch *dispatch; glamor_pixmap_fbo *fbo; GLenum format; @@ -276,8 +279,6 @@ glamor_fini_pixmap_fbo(ScreenPtr screen) void glamor_destroy_fbo(glamor_pixmap_fbo *fbo) { - glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; - list_del(&fbo->list); glamor_pixmap_fbo_cache_put(fbo); @@ -291,6 +292,7 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo; int cache_flag = GLAMOR_CACHE_TEXTURE; GLuint tex; + GLAMOR_DEFINE_CONTEXT; if (flag == GLAMOR_CREATE_TEXTURE_EXACT_SIZE) cache_flag |= GLAMOR_CACHE_EXACT_SIZE; @@ -303,6 +305,7 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, if (fbo == NULL) return NULL; + GLAMOR_SET_CONTEXT(glamor_priv); list_init(&fbo->list); dispatch = &glamor_priv->dispatch; @@ -319,6 +322,7 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, fbo->height = h; fbo->format = format; fbo->glamor_priv = glamor_priv; + GLAMOR_RESTORE_CONTEXT(glamor_priv); return fbo; } @@ -340,6 +344,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, GLenum format; GLint tex; int cache_flag; + GLAMOR_DEFINE_CONTEXT; if (!glamor_check_fbo_size(glamor_priv, w, h) || !glamor_check_fbo_depth(depth)) @@ -359,6 +364,8 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, if (fbo) return fbo; new_fbo: + + GLAMOR_SET_CONTEXT(glamor_priv); dispatch = &glamor_priv->dispatch; dispatch->glGenTextures(1, &tex); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -370,6 +377,7 @@ new_fbo: GL_UNSIGNED_BYTE, NULL); fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return fbo; } diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 97c4403ce..97e449784 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -40,6 +40,12 @@ _glamor_fill_spans(DrawablePtr drawable, BoxPtr pbox; int x1, x2, y; RegionPtr pClip = fbGetCompositeClip(gc); + glamor_screen_private *glamor_priv; + GLAMOR_DEFINE_CONTEXT; + Bool ret = FALSE; + + glamor_priv = glamor_get_screen_private(drawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; @@ -71,13 +77,15 @@ _glamor_fill_spans(DrawablePtr drawable, pbox++; } } - return TRUE; + ret = TRUE; + goto done; - fail: +fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable) - && glamor_ddx_fallback_check_gc(gc)) - return FALSE; + && glamor_ddx_fallback_check_gc(gc)) { + goto done; + } glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { @@ -88,7 +96,11 @@ _glamor_fill_spans(DrawablePtr drawable, } glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } - return TRUE; + ret = TRUE; + +done: + GLAMOR_RESTORE_CONTEXT(glamor_priv); + return ret; } diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 377783cb6..7caf2a372 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -46,8 +46,14 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, int no_alpha, no_revert; PixmapPtr temp_pixmap = NULL; glamor_gl_dispatch * dispatch; + GLAMOR_DEFINE_CONTEXT; + Bool ret = FALSE; goto fall_back; + + glamor_priv = glamor_get_screen_private(drawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); + if (format != ZPixmap) goto fall_back; @@ -113,10 +119,14 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, tex_type, d); if (temp_pixmap) glamor_destroy_pixmap(temp_pixmap); - return TRUE; + + ret = TRUE; fall_back: - miGetImage(drawable, x, y, w, h, format, planeMask, d); + + GLAMOR_RESTORE_CONTEXT(glamor_priv); + if (ret == FALSE) + miGetImage(drawable, x, y, w, h, format, planeMask, d); return TRUE; } diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 6c50d1b5b..2d30f37a8 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -49,7 +49,10 @@ _glamor_get_spans(DrawablePtr drawable, int i; uint8_t *readpixels_dst = (uint8_t *) dst; int x_off, y_off; + GLAMOR_DEFINE_CONTEXT; + Bool ret = FALSE; + GLAMOR_SET_CONTEXT(glamor_priv); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); goto fail; @@ -97,20 +100,24 @@ _glamor_get_spans(DrawablePtr drawable, } if (temp_pixmap) glamor_destroy_pixmap(temp_pixmap); - return TRUE; - fail: + ret = TRUE; + goto done; +fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) - return FALSE; + goto done; + 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); glamor_finish_access(drawable, GLAMOR_ACCESS_RO); } - return TRUE; +done: + GLAMOR_RESTORE_CONTEXT(glamor_priv); + return ret; } void diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c index c9a35a0f1..8c853e91a 100644 --- a/glamor/glamor_glyphblt.c +++ b/glamor/glamor_glyphblt.c @@ -37,15 +37,22 @@ _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) goto fail; + + glamor_priv = glamor_get_screen_private(pDrawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); glamor_prepare_access_gc(pGC); fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); glamor_finish_access_gc(pGC); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: return FALSE; @@ -72,15 +79,22 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) goto fail; + + glamor_priv = glamor_get_screen_private(pDrawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); glamor_prepare_access_gc(pGC); fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); glamor_finish_access_gc(pGC); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: return FALSE; @@ -106,11 +120,17 @@ static Bool _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable) && glamor_ddx_fallback_check_gc(pGC)) goto fail; + + glamor_priv = glamor_get_screen_private(pDrawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); glamor_prepare_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); glamor_prepare_access_gc(pGC); @@ -118,6 +138,7 @@ _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, glamor_finish_access_gc(pGC); glamor_finish_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: return FALSE; diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 32afd093b..8b362415f 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -45,8 +45,14 @@ _glamor_poly_fill_rect(DrawablePtr drawable, int xorg, yorg; int n; register BoxPtr pbox; - RegionPtr pClip = fbGetCompositeClip(gc); + Bool ret = FALSE; + glamor_screen_private *glamor_priv; + GLAMOR_DEFINE_CONTEXT; + + glamor_priv = glamor_get_screen_private(drawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { goto fail; } @@ -91,14 +97,15 @@ _glamor_poly_fill_rect(DrawablePtr drawable, goto fail; } } - return TRUE; + ret = TRUE; + goto done; - fail: +fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) - return FALSE; + goto done; glamor_fallback(" to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); @@ -109,7 +116,11 @@ _glamor_poly_fill_rect(DrawablePtr drawable, } glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } - return TRUE; + ret = TRUE; + +done: + GLAMOR_RESTORE_CONTEXT(glamor_priv); + return ret; } diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 0217e8fcb..0d37a1dd1 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -49,6 +49,9 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, xRectangle *rects; int x1, x2, y1, y2; int i; + glamor_screen_private *glamor_priv; + GLAMOR_DEFINE_CONTEXT; + /* 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 @@ -108,6 +111,8 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, && glamor_ddx_fallback_check_gc(gc)) return FALSE; + glamor_priv = glamor_get_screen_private(drawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); if (gc->lineWidth == 0) { if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { @@ -121,6 +126,7 @@ wide_line: /* fb calls mi functions in the lineWidth != 0 case. */ fbPolyLine(drawable, gc, mode, n, points); } + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; } diff --git a/glamor/glamor_polyops.c b/glamor/glamor_polyops.c index 6188bb23f..ca21b8b9a 100644 --- a/glamor/glamor_polyops.c +++ b/glamor/glamor_polyops.c @@ -36,15 +36,22 @@ static Bool _glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pDrawable)) goto fail; + + glamor_priv = glamor_get_screen_private(pDrawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access_gc(pGC); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); fbPolyPoint(pDrawable, pGC, mode, npt, ppt); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); glamor_finish_access_gc(pGC); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: @@ -69,10 +76,16 @@ static Bool _glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pDrawable)) goto fail; + + glamor_priv = glamor_get_screen_private(pDrawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); /* For lineWidth is not zero, fb calls to mi functions. */ if (pGC->lineWidth == 0) { glamor_prepare_access_gc(pGC); @@ -83,6 +96,7 @@ _glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, } else fbPolySegment(pDrawable, pGC, nseg, pSeg); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: @@ -107,11 +121,17 @@ static Bool _glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt, Bool fallback) { + GLAMOR_DEFINE_CONTEXT; + glamor_screen_private *glamor_priv; + if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pDrawable)) goto fail; /* For lineWidth is not zero, fb calls to mi functions. */ + + glamor_priv = glamor_get_screen_private(pDrawable->pScreen); + GLAMOR_SET_CONTEXT(glamor_priv); if (pGC->lineWidth == 0) { glamor_prepare_access_gc(pGC); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); @@ -121,6 +141,7 @@ _glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, } else fbPolyLine(pDrawable, pGC, mode, npt, ppt); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b19a30402..d04421b6a 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -219,6 +219,7 @@ typedef struct glamor_screen_private { int delayed_fallback_pending; glamor_pixmap_validate_function_t *pixmap_validate_funcs; int flags; + ScreenPtr screen; } glamor_screen_private; typedef enum glamor_access { diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 26d5cf766..581382261 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -230,7 +230,7 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, glamor_set_planemask(pixmap, ~0); glamor_fallback(": to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); - fail: +fail: if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); @@ -265,6 +265,10 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, GLfloat xscale, yscale, txscale, tyscale; GLuint tex; int no_alpha, no_revert; + GLAMOR_DEFINE_CONTEXT; + Bool ret = FALSE; + + GLAMOR_SET_CONTEXT(glamor_priv); if (image_format == XYBitmap) { assert(depth == 1); goto fail; @@ -396,14 +400,16 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); - return TRUE; - fail: + ret = TRUE; + goto done; + +fail: glamor_set_planemask(pixmap, ~0); if (!fallback && glamor_ddx_fallback_check_pixmap(&pixmap->drawable)) - return FALSE; + goto done; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); @@ -412,7 +418,11 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, left_pad, image_format, bits); glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RW); } - return TRUE; + ret = TRUE; + +done: + GLAMOR_RESTORE_CONTEXT(glamor_priv); + return ret; } void diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 789c684c2..b240eac6a 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -870,7 +870,10 @@ glamor_composite_with_shader(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); int vert_stride = 4; int nrect_max; + GLAMOR_DEFINE_CONTEXT; + Bool ret = FALSE; + GLAMOR_SET_CONTEXT(glamor_priv); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; @@ -1230,15 +1233,20 @@ glamor_composite_with_shader(CARD8 op, dispatch->glUseProgram(0); if (saved_source_format) source->format = saved_source_format; - return TRUE; - fail: + ret = TRUE; + goto done; + +fail: if (saved_source_format) source->format = saved_source_format; dispatch->glDisable(GL_BLEND); dispatch->glUseProgram(0); - return FALSE; + +done: + GLAMOR_RESTORE_CONTEXT(glamor_priv); + return ret; } static PicturePtr @@ -1308,11 +1316,11 @@ _glamor_composite(CARD8 op, int prect_size = ARRAY_SIZE(rect); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; Bool ret = TRUE; RegionRec region; BoxPtr box; int nbox, i, ok; + GLAMOR_DEFINE_CONTEXT; x_temp_src = x_source; y_temp_src = y_source; @@ -1320,6 +1328,7 @@ _glamor_composite(CARD8 op, y_temp_mask = y_mask; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + GLAMOR_SET_CONTEXT(glamor_priv); /* Currently. Always fallback to cpu if destination is in CPU memory. */ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { goto fail; @@ -1473,10 +1482,8 @@ _glamor_composite(CARD8 op, if (ok) goto done; - fail: +fail: - dispatch->glUseProgram(0); - dispatch->glDisable(GL_BLEND); if (!fallback && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable) && (!source_pixmap @@ -1528,6 +1535,7 @@ _glamor_composite(CARD8 op, FreePicture(temp_mask, 0); if (prect != rect) free(prect); + GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 26e774bc6..07c94ab57 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -47,7 +47,10 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; + GLAMOR_DEFINE_CONTEXT; + Bool ret = FALSE; + GLAMOR_SET_CONTEXT(glamor_priv); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); @@ -100,18 +103,25 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(dispatch, GXcopy); dispatch->glDisable(GL_SCISSOR_TEST); - return TRUE; - fail: + ret = TRUE; + goto done; + +fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) - return FALSE; + goto done; + 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); glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } - return TRUE; + ret = TRUE; + +done: + GLAMOR_RESTORE_CONTEXT(glamor_priv); + return ret; } void diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 74ce6cd0f..a66e24802 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -663,4 +663,33 @@ static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int } glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); } + +static inline void *glamor_make_current(ScreenPtr screen) +{ + return glamor_egl_make_current(screen); +} + +static inline void glamor_restore_current(ScreenPtr screen, void *previous_context) +{ + glamor_egl_restore_context(screen, previous_context); +} + +#ifdef GLX_USE_SHARED_DISPATCH +#define GLAMOR_DEFINE_CONTEXT void *_previous_context_ = NULL +#define GLAMOR_SET_CONTEXT(glamor_priv) \ + if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) \ + _previous_context_ = glamor_make_current(glamor_priv->screen) + +#define GLAMOR_RESTORE_CONTEXT(glamor_priv) \ + if ((glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) \ + && _previous_context_ != NULL) \ + glamor_restore_current(glamor_priv->screen, _previous_context_) +#else + +#define GLAMOR_DEFINE_CONTEXT +#define GLAMOR_SET_CONTEXT(glamor_priv) +#define GLAMOR_RESTORE_CONTEXT(glamor_priv) + +#endif + #endif diff --git a/glamor/glapi.h b/glamor/glapi.h new file mode 100644 index 000000000..da521aa7c --- /dev/null +++ b/glamor/glapi.h @@ -0,0 +1,121 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \mainpage Mesa GL API Module + * + * \section GLAPIIntroduction Introduction + * + * The Mesa GL API module is responsible for dispatching all the + * gl*() functions. All GL functions are dispatched by jumping through + * the current dispatch table (basically a struct full of function + * pointers.) + * + * A per-thread current dispatch table and per-thread current context + * pointer are managed by this module too. + * + * This module is intended to be non-Mesa-specific so it can be used + * with the X/DRI libGL also. + */ + +#ifndef _GLAPI_H +#define _GLAPI_H + +#define GL_GLEXT_PROTOTYPES + +#if GLAMOR_GLES2 +#include +#include +#else +#include +#include "GL/glext.h" +#endif + +/* Is this needed? It is incomplete anyway. */ +#ifdef USE_MGL_NAMESPACE +#define _glapi_set_dispatch _mglapi_set_dispatch +#define _glapi_get_dispatch _mglapi_get_dispatch +#define _glapi_set_context _mglapi_set_context +#define _glapi_get_context _mglapi_get_context +#define _glapi_Dispatch _mglapi_Dispatch +#define _glapi_Context _mglapi_Context +#endif + +typedef void (*_glapi_proc)(void); +struct _glapi_table; + + +#if defined (GLX_USE_TLS) + +extern __thread struct _glapi_table * _glapi_tls_Dispatch + __attribute__((tls_model("initial-exec"))); + +extern __thread void * _glapi_tls_Context + __attribute__((tls_model("initial-exec"))); + +extern const struct _glapi_table *_glapi_Dispatch; +extern const void *_glapi_Context; + +# define GET_DISPATCH() _glapi_tls_Dispatch +# define GET_CURRENT_CONTEXT(C) struct gl_context *C = (struct gl_context *) _glapi_tls_Context +# define SET_CURRENT_CONTEXT(C) _glapi_tls_Context = (void*)C + +#else + +extern struct _glapi_table *_glapi_Dispatch; +extern void *_glapi_Context; + +# ifdef THREADS + +# define GET_DISPATCH() \ + (likely(_glapi_Dispatch) ? _glapi_Dispatch : _glapi_get_dispatch()) + +# define GET_CURRENT_CONTEXT(C) struct gl_context *C = (struct gl_context *) \ + (likely(_glapi_Context) ? _glapi_Context : _glapi_get_context()) + + +# define SET_CURRENT_CONTEXT(C) do { if (likely(_glapi_Context)) \ + _glapi_Context = (void*)C; \ + else \ + _glapi_set_context(C); } while(0) + +# else + +# define GET_DISPATCH() _glapi_Dispatch +# define GET_CURRENT_CONTEXT(C) struct gl_context *C = (struct gl_context *) _glapi_Context +# define SET_CURRENT_CONTEXT(C) _glapi_Context = (void*)C + +# endif + +#endif /* defined (GLX_USE_TLS) */ + + +extern void +_glapi_set_context(void *context); + +extern void * +_glapi_get_context(void); + +#endif From 556adfa6b90f4c1ef12635cf78fa0bba046cf123 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 10 Feb 2012 12:54:44 +0000 Subject: [PATCH 302/462] Fixup glx support Renaming glamor_priv->dispatch and wrapping the access to the dispatch table with a function that also ensured the context was bound. dispatch = glamor_get_dispatch(glamor_priv); ... glamor_put_dispatch(glamor_priv); So that we catch all places where we attempt to call into GL withouta context. As an optimisation we can then do glamor_get_context(); glamor_put_context() around the rendering entry points to reduce the frequency of having to restore the old context. (Along with allowing the context to be recursively acquired and making the old context part of the glamor_egl state.) Reviewed-by: Zhigang Gong Signed-off-by: Zhigang Gong --- glamor/glamor.c | 21 ++++++----- glamor/glamor.h | 24 ++++++------- glamor/glamor_addtraps.c | 4 --- glamor/glamor_copyarea.c | 47 +++++++++++-------------- glamor/glamor_copyplane.c | 7 ---- glamor/glamor_copywindow.c | 4 --- glamor/glamor_core.c | 20 ++++++----- glamor/glamor_egl.c | 52 +++++++++++++++++----------- glamor/glamor_eglmodule.c | 4 +-- glamor/glamor_fbo.c | 25 ++++---------- glamor/glamor_fill.c | 26 +++++++------- glamor/glamor_fillspans.c | 7 ---- glamor/glamor_getimage.c | 12 ++----- glamor/glamor_getspans.c | 11 ++---- glamor/glamor_glyphblt.c | 24 ++----------- glamor/glamor_glyphs.c | 10 ++---- glamor/glamor_picture.c | 4 --- glamor/glamor_pixmap.c | 37 ++++++++++++-------- glamor/glamor_polyfillrect.c | 7 ---- glamor/glamor_polylines.c | 7 ---- glamor/glamor_polyops.c | 41 +++------------------- glamor/glamor_priv.h | 6 +--- glamor/glamor_putimage.c | 9 +++-- glamor/glamor_render.c | 67 +++++++++++++++++++----------------- glamor/glamor_setspans.c | 16 +++------ glamor/glamor_tile.c | 14 ++++---- glamor/glamor_triangles.c | 4 --- glamor/glamor_utils.h | 43 +++++++++++++++-------- glamor/glamor_window.c | 4 --- 29 files changed, 223 insertions(+), 334 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 6b6330f4c..86de1154b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -196,24 +196,25 @@ glamor_block_handler(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - GLAMOR_DEFINE_CONTEXT; + glamor_gl_dispatch *dispatch; - GLAMOR_SET_CONTEXT(glamor_priv); + dispatch = glamor_get_dispatch(glamor_priv); glamor_priv->tick++; dispatch->glFlush(); dispatch->glFinish(); glamor_fbo_expire(glamor_priv); - GLAMOR_RESTORE_CONTEXT(glamor_priv); + glamor_put_dispatch(glamor_priv); } static void _glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask) { - glamor_gl_dispatch *dispatch = data; + glamor_screen_private *glamor_priv = data; + glamor_gl_dispatch *dispatch = glamor_get_dispatch(glamor_priv); dispatch->glFlush(); dispatch->glFinish(); + glamor_put_dispatch(glamor_priv); } static void @@ -289,8 +290,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) } #endif - glamor_gl_dispatch_init(screen, &glamor_priv->dispatch, - gl_version); + glamor_gl_dispatch_init(screen, &glamor_priv->_dispatch, gl_version); #ifdef GLAMOR_GLES2 if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) { @@ -303,8 +303,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_gl_has_extension("GL_MESA_pack_invert"); glamor_priv->has_fbo_blit = glamor_gl_has_extension("GL_EXT_framebuffer_blit"); - glamor_priv->dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, - &glamor_priv->max_fbo_size); + glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, + &glamor_priv->max_fbo_size); glamor_set_debug_level(&glamor_debug_level); @@ -324,8 +324,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) if (flags & GLAMOR_USE_SCREEN) { if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, _glamor_wakeup_handler, - (void *) - &glamor_priv->dispatch)) { + glamor_priv)) { goto fail; } diff --git a/glamor/glamor.h b/glamor/glamor.h index 712a7a9b2..d3437d381 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -28,18 +28,16 @@ #ifndef GLAMOR_H #define GLAMOR_H -#include "scrnintstr.h" +#include #ifdef GLAMOR_FOR_XORG -#include "xf86str.h" +#include #endif -#include "pixmapstr.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "picturestr.h" -#include "fb.h" -#include "fbpict.h" - -#endif /* GLAMOR_H */ +#include +#include +#include +#include +#include +#include /* * glamor_pixmap_type : glamor pixmap's type. @@ -145,9 +143,8 @@ extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen); -extern _X_EXPORT void * glamor_egl_make_current(ScreenPtr screen); - -extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen, void *context); +extern _X_EXPORT void glamor_egl_make_current(ScreenPtr screen); +extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen); #ifdef GLAMOR_FOR_XORG @@ -320,3 +317,4 @@ extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, int extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points); +#endif /* GLAMOR_H */ diff --git a/glamor/glamor_addtraps.c b/glamor/glamor_addtraps.c index 28775e561..ac852963c 100644 --- a/glamor/glamor_addtraps.c +++ b/glamor/glamor_addtraps.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index e6569343e..de02224a3 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -21,10 +21,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_copyarea.c @@ -43,7 +39,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, glamor_pixmap_private *src_pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; int dst_x_off, dst_y_off, src_x_off, src_y_off, i; if (!glamor_priv->has_fbo_blit) { @@ -78,6 +74,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, } glamor_validate_pixmap(dst_pixmap); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->fbo->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, @@ -136,6 +133,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, GL_NEAREST); } } + glamor_put_dispatch(glamor_priv); return TRUE; } #endif @@ -147,7 +145,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, { glamor_screen_private *glamor_priv = glamor_get_screen_private(dst->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); int i; @@ -158,23 +156,24 @@ glamor_copy_n_to_n_textured(DrawablePtr src, enum glamor_pixmap_status src_status = GLAMOR_NONE; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; int flush_needed = 0; + int alu = GXcopy; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n"); - goto fail; + return FALSE; } if (!src_pixmap_priv || !src_pixmap_priv->gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); - goto fail; + return FALSE; #else src_status = glamor_upload_pixmap_to_texture(src_pixmap); if (src_status != GLAMOR_UPLOAD_DONE) - goto fail; + return FALSE; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); #endif @@ -182,25 +181,26 @@ glamor_copy_n_to_n_textured(DrawablePtr src, flush_needed = 1; if (gc) { - glamor_set_alu(dispatch, gc->alu); if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - goto fail; - if (gc->alu != GXcopy) { - glamor_set_destination_pixmap_priv_nc - (src_pixmap_priv); - glamor_validate_pixmap(src_pixmap); - } + return FALSE; + alu = gc->alu; } - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - glamor_validate_pixmap(dst_pixmap); - pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); + dispatch = glamor_get_dispatch(glamor_priv); + + glamor_set_alu(dispatch, alu); + if (alu != GXcopy) { + glamor_set_destination_pixmap_priv_nc (src_pixmap_priv); + glamor_validate_pixmap(src_pixmap); + } + glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); + glamor_validate_pixmap(dst_pixmap); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); @@ -284,12 +284,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, /* The source texture is bound to a fbo, we have to flush it here. */ if (flush_needed) dispatch->glFlush(); + glamor_put_dispatch(glamor_priv); return TRUE; - - fail: - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(dst_pixmap, ~0); - return FALSE; } static Bool @@ -317,7 +313,6 @@ _glamor_copy_n_to_n(DrawablePtr src, int i; int overlaped = 0; Bool ret = FALSE; - GLAMOR_DEFINE_CONTEXT; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); @@ -326,7 +321,6 @@ _glamor_copy_n_to_n(DrawablePtr src, screen = dst_pixmap->drawable.pScreen; glamor_priv = glamor_get_screen_private(dst->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { glamor_fallback("dest pixmap %p has no fbo. \n", @@ -448,7 +442,6 @@ _glamor_copy_n_to_n(DrawablePtr src, glamor_clear_delayed_fallbacks(dst->pScreen); if (temp_src != src) glamor_destroy_pixmap(temp_pixmap); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c index b6b26a50c..6487ff7fc 100644 --- a/glamor/glamor_copyplane.c +++ b/glamor/glamor_copyplane.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool @@ -37,7 +33,6 @@ _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane, RegionPtr *pRegion, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; glamor_screen_private *glamor_priv; if (!fallback @@ -47,14 +42,12 @@ _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, goto fail; glamor_priv = glamor_get_screen_private(pDst->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDst, GLAMOR_ACCESS_RW); glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO); *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); glamor_finish_access(pSrc, GLAMOR_ACCESS_RO); glamor_finish_access(pDst, GLAMOR_ACCESS_RW); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: diff --git a/glamor/glamor_copywindow.c b/glamor/glamor_copywindow.c index 11b30363f..b181ff529 100644 --- a/glamor/glamor_copywindow.c +++ b/glamor/glamor_copywindow.c @@ -21,10 +21,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_copywindow.c diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 01c9aeaf9..0376388ca 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -31,10 +31,6 @@ * This file covers core X rendering in glamor. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include #include "glamor_priv.h" @@ -174,7 +170,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) GLint sampler_uniform_location; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); glamor_priv->finish_access_prog[0] = dispatch->glCreateProgram(); glamor_priv->finish_access_prog[1] = dispatch->glCreateProgram(); @@ -248,7 +244,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) dispatch->glUniform1i(sampler_uniform_location, 0); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1], 0); dispatch->glUseProgram(0); - + glamor_put_dispatch(glamor_priv); } void @@ -258,9 +254,10 @@ glamor_fini_finish_access_shaders(ScreenPtr screen) glamor_gl_dispatch *dispatch; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glDeleteProgram(glamor_priv->finish_access_prog[0]); dispatch->glDeleteProgram(glamor_priv->finish_access_prog[1]); + glamor_put_dispatch(glamor_priv); } void @@ -271,7 +268,6 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv)) return; @@ -281,11 +277,17 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) } if (pixmap_priv->fbo->pbo != 0 && pixmap_priv->fbo->pbo_valid) { + glamor_gl_dispatch *dispatch; + assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); + + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - pixmap_priv->fbo->pbo_valid = FALSE; dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); + glamor_put_dispatch(glamor_priv); + + pixmap_priv->fbo->pbo_valid = FALSE; pixmap_priv->fbo->pbo = 0; } else { free(pixmap->devPrivate.ptr); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index a339527d8..ecbc186fa 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -31,11 +31,8 @@ #include "config.h" #endif -#ifdef HAVE_DIX_CONFIG_H -#include -#endif #define GLAMOR_FOR_XORG -#include "xorg-server.h" +#include #include #include #include @@ -93,7 +90,8 @@ struct glamor_egl_screen_private { struct gbm_device *gbm; #endif int has_gem; - void *gl_context; + void *gl_context, *old_context; + int gl_context_depth; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; @@ -112,13 +110,18 @@ glamor_egl_get_screen_private(ScrnInfoPtr scrn) scrn->privates[xf86GlamorEGLPrivateIndex].ptr; } #ifdef GLX_USE_SHARED_DISPATCH -_X_EXPORT void * +_X_EXPORT void glamor_egl_make_current(ScreenPtr screen) { ScrnInfoPtr scrn = xf86Screens[screen->myNum]; struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); + + if (glamor_egl->gl_context_depth++) + return; + GET_CURRENT_CONTEXT(current); + glamor_egl->old_context = current; if (glamor_egl->gl_context != current) { eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE, @@ -126,24 +129,28 @@ glamor_egl_make_current(ScreenPtr screen) if (!eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, - "Failed to make EGL context current\n"); - return NULL; + FatalError("Failed to make EGL context current\n"); } - return current; } - return NULL; } _X_EXPORT void -glamor_egl_restore_context(ScreenPtr screen, void *context) +glamor_egl_restore_context(ScreenPtr screen) { - if (context) - SET_CURRENT_CONTEXT(context); + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + + if (--glamor_egl->gl_context_depth) + return; + + if (glamor_egl->old_context && + glamor_egl->gl_context != glamor_egl->old_context) + SET_CURRENT_CONTEXT(glamor_egl->old_context); } #else -#define glamor_egl_make_current(x) NULL -#define glamor_egl_restore_context(s, c) +#define glamor_egl_make_current(x) +#define glamor_egl_restore_context(s) #endif static EGLImageKHR @@ -252,12 +259,11 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) EGLImageKHR image; GLuint texture; int name; - void *prev_context; Bool ret = FALSE; glamor_egl = glamor_egl_get_screen_private(scrn); - prev_context = glamor_egl_make_current(screen); + glamor_egl_make_current(screen); if (glamor_egl->has_gem) { if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, @@ -285,8 +291,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) ret = TRUE; done: - if (prev_context) - glamor_egl_restore_context(screen, prev_context); + glamor_egl_restore_context(screen); return ret; } @@ -497,6 +502,13 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) #endif glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; +#ifdef GLAMOR_GLES2 + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using GLES2.\n"); +#ifdef GLX_USE_SHARED_DISPATCH + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Glamor is using GLES2 but GLX needs GL. " + "Indirect GLX may not work correctly.\n"); +#endif +#endif return TRUE; } diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c index e1f6672af..096165162 100644 --- a/glamor/glamor_eglmodule.c +++ b/glamor/glamor_eglmodule.c @@ -28,10 +28,10 @@ #include "config.h" #endif -#include #define GLAMOR_FOR_XORG #include "glamor.h" -#include "xf86Module.h" +#include +#include static XF86ModuleVersionInfo VersRec = { GLAMOR_EGL_MODULE_NAME, diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 929cababa..e5675d81c 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -1,7 +1,3 @@ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include #include "glamor_priv.h" @@ -126,17 +122,14 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, void glamor_purge_fbo(glamor_pixmap_fbo *fbo) { - GLAMOR_DEFINE_CONTEXT; - - GLAMOR_SET_CONTEXT(fbo->glamor_priv); - glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + glamor_gl_dispatch *dispatch = glamor_get_dispatch(fbo->glamor_priv); if (fbo->fb) dispatch->glDeleteFramebuffers(1, &fbo->fb); if (fbo->tex) dispatch->glDeleteTextures(1, &fbo->tex); if (fbo->pbo) dispatch->glDeleteBuffers(1, &fbo->pbo); - GLAMOR_RESTORE_CONTEXT(fbo->glamor_priv); + glamor_put_dispatch(fbo->glamor_priv); free(fbo); } @@ -292,7 +285,6 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo; int cache_flag = GLAMOR_CACHE_TEXTURE; GLuint tex; - GLAMOR_DEFINE_CONTEXT; if (flag == GLAMOR_CREATE_TEXTURE_EXACT_SIZE) cache_flag |= GLAMOR_CACHE_EXACT_SIZE; @@ -305,10 +297,9 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, if (fbo == NULL) return NULL; - GLAMOR_SET_CONTEXT(glamor_priv); list_init(&fbo->list); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glGenTextures(1, &tex); dispatch->glBindTexture(GL_TEXTURE_2D, tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -317,12 +308,13 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, GL_NEAREST); dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); + glamor_put_dispatch(glamor_priv); + fbo->tex = tex; fbo->width = w; fbo->height = h; fbo->format = format; fbo->glamor_priv = glamor_priv; - GLAMOR_RESTORE_CONTEXT(glamor_priv); return fbo; } @@ -344,7 +336,6 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, GLenum format; GLint tex; int cache_flag; - GLAMOR_DEFINE_CONTEXT; if (!glamor_check_fbo_size(glamor_priv, w, h) || !glamor_check_fbo_depth(depth)) @@ -364,9 +355,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, if (fbo) return fbo; new_fbo: - - GLAMOR_SET_CONTEXT(glamor_priv); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glGenTextures(1, &tex); dispatch->glBindTexture(GL_TEXTURE_2D, tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -377,7 +366,7 @@ new_fbo: GL_UNSIGNED_BYTE, NULL); fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); - GLAMOR_RESTORE_CONTEXT(glamor_priv); + glamor_put_dispatch(glamor_priv); return fbo; } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index b462f5922..85733099b 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -21,10 +21,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_fillspans.c @@ -112,7 +108,7 @@ glamor_init_solid_shader(ScreenPtr screen) GLint fs_prog, vs_prog; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); glamor_priv->solid_prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs); fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, @@ -127,6 +123,7 @@ glamor_init_solid_shader(ScreenPtr screen) glamor_priv->solid_color_uniform_location = dispatch->glGetUniformLocation(glamor_priv->solid_prog, "color"); + glamor_put_dispatch(glamor_priv); } void @@ -136,8 +133,9 @@ glamor_fini_solid_shader(ScreenPtr screen) glamor_gl_dispatch *dispatch; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glDeleteProgram(glamor_priv->solid_prog); + glamor_put_dispatch(glamor_priv); } Bool @@ -150,7 +148,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_get_screen_private(screen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; int x1 = x; int x2 = x + width; int y1 = y; @@ -158,15 +156,16 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GLfloat color[4]; float vertices[8]; GLfloat xscale, yscale; + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("dest %p has no fbo.\n", pixmap); - goto fail; + return FALSE; } - glamor_set_alu(dispatch, alu); + if (!glamor_set_planemask(pixmap, planemask)) { glamor_fallback ("Failedto set planemask in glamor_solid.\n"); - goto fail; + return FALSE; } glamor_get_rgba_from_pixel(fg_pixel, @@ -189,6 +188,8 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); + dispatch = glamor_get_dispatch(glamor_priv); + glamor_set_alu(dispatch, alu); dispatch->glUseProgram(glamor_priv->solid_prog); dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, @@ -205,9 +206,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); return TRUE; - fail: - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(pixmap, ~0); - return FALSE; } diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 97e449784..6598249fd 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -20,10 +20,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - /** @file glamor_fillspans.c * * FillSpans implementation, taken from fb_fillsp.c @@ -41,11 +37,9 @@ _glamor_fill_spans(DrawablePtr drawable, int x1, x2, y; RegionPtr pClip = fbGetCompositeClip(gc); glamor_screen_private *glamor_priv; - GLAMOR_DEFINE_CONTEXT; Bool ret = FALSE; glamor_priv = glamor_get_screen_private(drawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; @@ -99,7 +93,6 @@ fail: ret = TRUE; done: - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 7caf2a372..efbd1baca 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" @@ -46,13 +42,11 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, int no_alpha, no_revert; PixmapPtr temp_pixmap = NULL; glamor_gl_dispatch * dispatch; - GLAMOR_DEFINE_CONTEXT; Bool ret = FALSE; goto fall_back; glamor_priv = glamor_get_screen_private(drawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); if (format != ZPixmap) goto fall_back; @@ -65,7 +59,6 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, } glamor_priv = glamor_get_screen_private(drawable->pScreen); pixmap_priv = glamor_get_pixmap_private(pixmap); - dispatch = &glamor_priv->dispatch; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -97,6 +90,8 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, int row_length = PixmapBytePad(w, drawable->depth); row_length = (row_length * 8) / drawable->bitsPerPixel; + + dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); @@ -117,14 +112,13 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, h, tex_format, tex_type, d); + glamor_put_dispatch(glamor_priv); if (temp_pixmap) glamor_destroy_pixmap(temp_pixmap); ret = TRUE; fall_back: - - GLAMOR_RESTORE_CONTEXT(glamor_priv); if (ret == FALSE) miGetImage(drawable, x, y, w, h, format, planeMask, d); return TRUE; diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 2d30f37a8..91030a3d4 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -25,10 +25,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool @@ -44,15 +40,13 @@ _glamor_get_spans(DrawablePtr drawable, glamor_get_screen_private(drawable->pScreen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; PixmapPtr temp_pixmap = NULL; int i; uint8_t *readpixels_dst = (uint8_t *) dst; int x_off, y_off; - GLAMOR_DEFINE_CONTEXT; Bool ret = FALSE; - GLAMOR_SET_CONTEXT(glamor_priv); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); goto fail; @@ -82,6 +76,7 @@ _glamor_get_spans(DrawablePtr drawable, } glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + dispatch = glamor_get_dispatch(glamor_priv); for (i = 0; i < count; i++) { if (glamor_priv->yInverted) { dispatch->glReadPixels(points[i].x + x_off, @@ -98,6 +93,7 @@ _glamor_get_spans(DrawablePtr drawable, readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } + glamor_put_dispatch(glamor_priv); if (temp_pixmap) glamor_destroy_pixmap(temp_pixmap); @@ -116,7 +112,6 @@ fail: glamor_finish_access(drawable, GLAMOR_ACCESS_RO); } done: - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c index 8c853e91a..163099847 100644 --- a/glamor/glamor_glyphblt.c +++ b/glamor/glamor_glyphblt.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool @@ -37,7 +33,6 @@ _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; glamor_screen_private *glamor_priv; if (!fallback @@ -46,13 +41,11 @@ _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, goto fail; glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); glamor_prepare_access_gc(pGC); fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); glamor_finish_access_gc(pGC); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; fail: return FALSE; @@ -79,25 +72,20 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; glamor_screen_private *glamor_priv; if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) - goto fail; + return FALSE; glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); glamor_prepare_access_gc(pGC); fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); glamor_finish_access_gc(pGC); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; - fail: - return FALSE; } void @@ -120,17 +108,12 @@ static Bool _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable) && glamor_ddx_fallback_check_gc(pGC)) - goto fail; + return FALSE; - glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); glamor_prepare_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); glamor_prepare_access_gc(pGC); @@ -138,10 +121,7 @@ _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, glamor_finish_access_gc(pGC); glamor_finish_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; - fail: - return FALSE; } void diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 33e06f1d3..fe7d9de26 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -40,15 +40,11 @@ * Based on code by: Keith Packard */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include #include "glamor_priv.h" -#include "mipict.h" +#include #if DEBUG_GLYPH_CACHE #define DBG_GLYPH_CACHE(a) ErrorF a @@ -163,7 +159,7 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) glamor_glyph_cache_t *cache = &glamor->glyphCaches[i]; PixmapPtr pixmap; PicturePtr picture; - CARD32 component_alpha; + XID component_alpha; int depth = PIXMAN_FORMAT_DEPTH(formats[i]); int error; PictFormatPtr pPictFormat = @@ -652,7 +648,7 @@ glamor_glyphs_via_mask(CARD8 op, GlyphPtr glyph; int error; BoxRec extents = { 0, 0, 0, 0 }; - CARD32 component_alpha; + XID component_alpha; glamor_glyph_buffer_t buffer; xRectangle fill_rect; diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 217fd4048..38185a491 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -1,7 +1,3 @@ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include #include "glamor_priv.h" diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 1a63ffdd1..7f4a90b81 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -1,7 +1,3 @@ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include #include "glamor_priv.h" @@ -31,7 +27,7 @@ static void _glamor_pixmap_validate_filling(glamor_screen_private * glamor_priv, glamor_pixmap_private * pixmap_priv) { - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch = glamor_get_dispatch(glamor_priv); GLfloat vertices[8]; dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), @@ -52,6 +48,7 @@ _glamor_pixmap_validate_filling(glamor_screen_private * glamor_priv, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; + glamor_put_dispatch(glamor_priv); } @@ -94,7 +91,7 @@ glamor_validate_pixmap(PixmapPtr pixmap) void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { - glamor_gl_dispatch *dispatch = &pixmap_priv->glamor_priv->dispatch; + glamor_gl_dispatch *dispatch = glamor_get_dispatch(pixmap_priv->glamor_priv); dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fbo->fb); #ifndef GLAMOR_GLES2 dispatch->glMatrixMode(GL_PROJECTION); @@ -106,6 +103,7 @@ glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) pixmap_priv->fbo->width, pixmap_priv->fbo->height); + glamor_put_dispatch(pixmap_priv->glamor_priv); } int @@ -222,7 +220,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; unsigned int stride, row_length; void *texels; GLenum iformat; @@ -235,6 +233,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, stride = pixmap->devKind; row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindTexture(GL_TEXTURE_2D, tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -271,6 +270,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glamor_put_dispatch(glamor_priv); } @@ -289,7 +289,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; static float vertices[8]; static float texcoords[8] = { 0, 1, 1, 1, @@ -339,6 +339,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, vertices); /* Slow path, we need to flip y or wire alpha to 1. */ + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); @@ -379,13 +380,17 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glDeleteTextures(1, &tex); dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glamor_put_dispatch(glamor_priv); } void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) { + glamor_gl_dispatch *dispatch; int status; - glamor_gl_dispatch *dispatch = &fbo->glamor_priv->dispatch; + + dispatch = glamor_get_dispatch(fbo->glamor_priv); if (fbo->fb == 0) dispatch->glGenFramebuffers(1, &fbo->fb); @@ -422,11 +427,10 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) break; } - LogMessageVerb(X_INFO, 0, - "destination is framebuffer incomplete: %s [%#x]\n", - str, status); - assert(0); + FatalError("destination is framebuffer incomplete: %s [%#x]\n", + str, status); } + glamor_put_dispatch(fbo->glamor_priv); } /* @@ -571,7 +575,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, glamor_priv = glamor_get_screen_private(screen); source_priv = glamor_get_pixmap_private(source); - dispatch = &glamor_priv->dispatch; if (*format == GL_BGRA) { *format = GL_RGBA; swap_rb = 1; @@ -585,6 +588,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -631,6 +635,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); return temp_pixmap; } @@ -657,7 +662,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -715,6 +720,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); @@ -795,6 +801,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); + glamor_put_dispatch(glamor_priv); done: pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 8b362415f..61e707f59 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_fillspans.c @@ -48,10 +44,8 @@ _glamor_poly_fill_rect(DrawablePtr drawable, RegionPtr pClip = fbGetCompositeClip(gc); Bool ret = FALSE; glamor_screen_private *glamor_priv; - GLAMOR_DEFINE_CONTEXT; glamor_priv = glamor_get_screen_private(drawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { goto fail; @@ -119,7 +113,6 @@ fail: ret = TRUE; done: - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 0d37a1dd1..175e9580d 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_polylines.c @@ -50,7 +46,6 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, int x1, x2, y1, y2; int i; glamor_screen_private *glamor_priv; - GLAMOR_DEFINE_CONTEXT; /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0) { @@ -112,7 +107,6 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, return FALSE; glamor_priv = glamor_get_screen_private(drawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); if (gc->lineWidth == 0) { if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { @@ -126,7 +120,6 @@ wide_line: /* fb calls mi functions in the lineWidth != 0 case. */ fbPolyLine(drawable, gc, mode, n, points); } - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; } diff --git a/glamor/glamor_polyops.c b/glamor/glamor_polyops.c index ca21b8b9a..7320c1762 100644 --- a/glamor/glamor_polyops.c +++ b/glamor/glamor_polyops.c @@ -26,36 +26,23 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool _glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pDrawable)) - goto fail; + return FALSE; - glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); glamor_prepare_access_gc(pGC); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); fbPolyPoint(pDrawable, pGC, mode, npt, ppt); glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); glamor_finish_access_gc(pGC); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; - -fail: - return FALSE; } void @@ -76,16 +63,11 @@ static Bool _glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pDrawable)) - goto fail; + return FALSE; - glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); /* For lineWidth is not zero, fb calls to mi functions. */ if (pGC->lineWidth == 0) { glamor_prepare_access_gc(pGC); @@ -94,13 +76,9 @@ _glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); glamor_finish_access_gc(pGC); } else - fbPolySegment(pDrawable, pGC, nseg, pSeg); + fbPolySegment(pDrawable, pGC, nseg, pSeg); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; - -fail: - return FALSE; } void @@ -121,17 +99,12 @@ static Bool _glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt, Bool fallback) { - GLAMOR_DEFINE_CONTEXT; - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pDrawable)) - goto fail; + return FALSE; /* For lineWidth is not zero, fb calls to mi functions. */ - glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - GLAMOR_SET_CONTEXT(glamor_priv); if (pGC->lineWidth == 0) { glamor_prepare_access_gc(pGC); glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); @@ -139,13 +112,9 @@ _glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); glamor_finish_access_gc(pGC); } else - fbPolyLine(pDrawable, pGC, mode, npt, ppt); + fbPolyLine(pDrawable, pGC, mode, npt, ppt); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return TRUE; - -fail: - return FALSE; } void diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index d04421b6a..05bb18ac1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -31,10 +31,6 @@ #include "config.h" #endif -#ifdef HAVE_DIX_CONFIG_H -#include -#include -#endif #include #include "glamor.h" @@ -171,7 +167,7 @@ struct glamor_saved_procs { (((int)(t1) - (int)(t0)) < 0) typedef struct glamor_screen_private { - struct glamor_gl_dispatch dispatch; + struct glamor_gl_dispatch _dispatch; int yInverted; unsigned int tick; enum glamor_gl_flavor gl_flavor; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 581382261..75e5b4cdd 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -251,7 +251,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, { glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -265,10 +265,8 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, GLfloat xscale, yscale, txscale, tyscale; GLuint tex; int no_alpha, no_revert; - GLAMOR_DEFINE_CONTEXT; Bool ret = FALSE; - GLAMOR_SET_CONTEXT(glamor_priv); if (image_format == XYBitmap) { assert(depth == 1); goto fail; @@ -287,7 +285,6 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (!glamor_set_planemask(pixmap, gc->planemask)) { goto fail; } - glamor_set_alu(dispatch, gc->alu); if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, @@ -298,6 +295,8 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } /* XXX consider to reuse a function to do the following work. */ + dispatch = glamor_get_dispatch(glamor_priv); + glamor_set_alu(dispatch, gc->alu); glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -400,6 +399,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); + glamor_put_dispatch(glamor_priv); ret = TRUE; goto done; @@ -421,7 +421,6 @@ fail: ret = TRUE; done: - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b240eac6a..89e8265a8 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -220,15 +220,16 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, GLuint vs, fs, prog; GLint source_sampler_uniform_location, mask_sampler_uniform_location; - glamor_screen_private *glamor = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor->dispatch; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch; + dispatch = glamor_get_dispatch(glamor_priv); vs = glamor_create_composite_vs(dispatch, key); if (vs == 0) - return; + goto out; fs = glamor_create_composite_fs(dispatch, key); if (fs == 0) - return; + goto out; prog = dispatch->glCreateProgram(); dispatch->glAttachShader(prog, vs); @@ -268,6 +269,9 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, (mask_sampler_uniform_location, 1); } } + +out: + glamor_put_dispatch(glamor_priv); } static glamor_composite_shader * @@ -316,7 +320,7 @@ glamor_init_composite_shaders(ScreenPtr screen) int vb_size; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glGenBuffers(1, &glamor_priv->vbo); dispatch->glGenBuffers(1, &glamor_priv->ebo); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); @@ -331,17 +335,13 @@ glamor_init_composite_shaders(ScreenPtr screen) } else { vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2); - if (vb == NULL) { - ErrorF("Failed to allocate vb memory.\n"); - exit(1); - } + if (vb == NULL) + FatalError("Failed to allocate vb memory.\n"); eb = malloc(eb_size); } - if (eb == NULL) { - ErrorF("fatal error, fail to get eb.\n"); - exit(1); - } + if (eb == NULL) + FatalError("fatal error, fail to get eb.\n"); glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { @@ -362,6 +362,8 @@ glamor_init_composite_shaders(ScreenPtr screen) free(eb); glamor_priv->vb = (char*)vb; } + + glamor_put_dispatch(glamor_priv); } void @@ -373,7 +375,7 @@ glamor_fini_composite_shaders(ScreenPtr screen) int i,j,k; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glDeleteBuffers(1, &glamor_priv->vbo); dispatch->glDeleteBuffers(1, &glamor_priv->ebo); @@ -388,8 +390,9 @@ glamor_fini_composite_shaders(ScreenPtr screen) if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb) free(glamor_priv->vb); -} + glamor_put_dispatch(glamor_priv); +} static Bool glamor_set_composite_op(ScreenPtr screen, @@ -399,7 +402,7 @@ glamor_set_composite_op(ScreenPtr screen, struct blendinfo *op_info; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; if (op >= ARRAY_SIZE(composite_op_info)) { glamor_fallback("unsupported render op %d \n", op); @@ -435,12 +438,14 @@ glamor_set_composite_op(ScreenPtr screen, dest_blend = GL_ONE_MINUS_SRC_COLOR; } + dispatch = glamor_get_dispatch(glamor_priv); if (source_blend == GL_ONE && dest_blend == GL_ZERO) { dispatch->glDisable(GL_BLEND); } else { dispatch->glEnable(GL_BLEND); dispatch->glBlendFunc(source_blend, dest_blend); } + glamor_put_dispatch(glamor_priv); return TRUE; } @@ -451,7 +456,6 @@ glamor_composite_texture_fixup(ScreenPtr screen, { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; Bool has_repeat; int width, height; @@ -478,7 +482,9 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; + + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glActiveTexture(GL_TEXTURE0 + unit); dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); switch (picture->repeatType) { @@ -533,6 +539,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif + glamor_put_dispatch(glamor_priv); } static void @@ -654,7 +661,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; glamor_priv->vbo_offset = 0; glamor_priv->vbo_offset = 0; @@ -667,6 +674,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) if (glamor_priv->has_mask_coords) glamor_priv->vb_stride += 2 * sizeof(float); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { dispatch->glBufferData(GL_ARRAY_BUFFER, @@ -706,6 +714,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) sizeof(float))); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK); } + glamor_put_dispatch(glamor_priv); } static void @@ -739,9 +748,12 @@ glamor_flush_composite_rects(ScreenPtr screen) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; + if (!glamor_priv->render_nr_verts) return; + + dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); else { @@ -754,6 +766,7 @@ glamor_flush_composite_rects(ScreenPtr screen) dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, GL_UNSIGNED_SHORT, NULL); + glamor_put_dispatch(glamor_priv); } static void @@ -846,7 +859,7 @@ glamor_composite_with_shader(CARD8 op, ScreenPtr screen = dest->pDrawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; @@ -870,10 +883,8 @@ glamor_composite_with_shader(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); int vert_stride = 4; int nrect_max; - GLAMOR_DEFINE_CONTEXT; Bool ret = FALSE; - GLAMOR_SET_CONTEXT(glamor_priv); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; @@ -1090,6 +1101,7 @@ glamor_composite_with_shader(CARD8 op, goto fail; } + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glUseProgram(shader->prog); if (key.source == SHADER_SOURCE_SOLID) { @@ -1233,6 +1245,7 @@ glamor_composite_with_shader(CARD8 op, dispatch->glUseProgram(0); if (saved_source_format) source->format = saved_source_format; + glamor_put_dispatch(glamor_priv); ret = TRUE; goto done; @@ -1240,12 +1253,7 @@ glamor_composite_with_shader(CARD8 op, fail: if (saved_source_format) source->format = saved_source_format; - - dispatch->glDisable(GL_BLEND); - dispatch->glUseProgram(0); - done: - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } @@ -1320,7 +1328,6 @@ _glamor_composite(CARD8 op, RegionRec region; BoxPtr box; int nbox, i, ok; - GLAMOR_DEFINE_CONTEXT; x_temp_src = x_source; y_temp_src = y_source; @@ -1328,7 +1335,6 @@ _glamor_composite(CARD8 op, y_temp_mask = y_mask; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - GLAMOR_SET_CONTEXT(glamor_priv); /* Currently. Always fallback to cpu if destination is in CPU memory. */ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { goto fail; @@ -1535,7 +1541,6 @@ fail: FreePicture(temp_mask, 0); if (prect != rect) free(prect); - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index 07c94ab57..a9471698a 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -25,10 +25,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool @@ -40,17 +36,15 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_pixmap_private *dest_pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; GLenum format, type; int no_alpha, no_revert, i; uint8_t *drawpixels_src = (uint8_t *) src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; - GLAMOR_DEFINE_CONTEXT; Bool ret = FALSE; - GLAMOR_SET_CONTEXT(glamor_priv); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); @@ -70,17 +64,15 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, goto fail; } - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); glamor_validate_pixmap(dest_pixmap); - if (!glamor_set_planemask(dest_pixmap, gc->planemask)) - goto fail; - glamor_set_alu(dispatch, gc->alu); if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); + dispatch = glamor_get_dispatch(glamor_priv); + glamor_set_alu(dispatch, gc->alu); for (i = 0; i < n; i++) { n = REGION_NUM_RECTS(clip); @@ -103,6 +95,7 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_set_planemask(dest_pixmap, ~0); glamor_set_alu(dispatch, GXcopy); dispatch->glDisable(GL_SCISSOR_TEST); + glamor_put_dispatch(glamor_priv); ret = TRUE; goto done; @@ -120,7 +113,6 @@ fail: ret = TRUE; done: - GLAMOR_RESTORE_CONTEXT(glamor_priv); return ret; } diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 3087bea6e..917078fa2 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -25,10 +25,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_tile.c @@ -60,7 +56,7 @@ glamor_init_tile_shader(ScreenPtr screen) GLint sampler_uniform_location; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); glamor_priv->tile_prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs); fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, @@ -81,6 +77,7 @@ glamor_init_tile_shader(ScreenPtr screen) dispatch->glUseProgram(glamor_priv->tile_prog); dispatch->glUniform1i(sampler_uniform_location, 0); dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); } void @@ -90,8 +87,9 @@ glamor_fini_tile_shader(ScreenPtr screen) glamor_gl_dispatch *dispatch; glamor_priv = glamor_get_screen_private(screen); - dispatch = &glamor_priv->dispatch; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glDeleteProgram(glamor_priv->tile_prog); + glamor_put_dispatch(glamor_priv); } Bool @@ -103,7 +101,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + glamor_gl_dispatch *dispatch; int x1 = x; int x2 = x + width; int y1 = y; @@ -161,6 +159,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_validate_pixmap(pixmap); pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + dispatch = glamor_get_dispatch(glamor_priv); glamor_set_alu(dispatch, alu); if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { @@ -219,6 +218,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, dispatch->glUseProgram(0); glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); + glamor_put_dispatch(glamor_priv); return TRUE; fail: diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c index 208ac77f1..e0f4a9708 100644 --- a/glamor/glamor_triangles.c +++ b/glamor/glamor_triangles.c @@ -26,10 +26,6 @@ * */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" static Bool diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index a66e24802..4a51ba59e 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -664,31 +664,44 @@ static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); } -static inline void *glamor_make_current(ScreenPtr screen) +static inline void glamor_make_current(ScreenPtr screen) { - return glamor_egl_make_current(screen); + glamor_egl_make_current(screen); } -static inline void glamor_restore_current(ScreenPtr screen, void *previous_context) +static inline void glamor_restore_current(ScreenPtr screen) { - glamor_egl_restore_context(screen, previous_context); + glamor_egl_restore_context(screen); } #ifdef GLX_USE_SHARED_DISPATCH -#define GLAMOR_DEFINE_CONTEXT void *_previous_context_ = NULL -#define GLAMOR_SET_CONTEXT(glamor_priv) \ - if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) \ - _previous_context_ = glamor_make_current(glamor_priv->screen) +static inline glamor_gl_dispatch * +glamor_get_dispatch(glamor_screen_private *glamor_priv) +{ + if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) + glamor_make_current(glamor_priv->screen); -#define GLAMOR_RESTORE_CONTEXT(glamor_priv) \ - if ((glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) \ - && _previous_context_ != NULL) \ - glamor_restore_current(glamor_priv->screen, _previous_context_) + return &glamor_priv->_dispatch; +} + +static inline void +glamor_put_dispatch(glamor_screen_private *glamor_priv) +{ + if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) + glamor_restore_current(glamor_priv->screen); +} #else +#warning "Indirect GLX may be broken, need to implement context switch." +static inline glamor_gl_dispatch * +glamor_get_dispatch(glamor_screen_private *glamor_priv) +{ + return &glamor_priv->_dispatch; +} -#define GLAMOR_DEFINE_CONTEXT -#define GLAMOR_SET_CONTEXT(glamor_priv) -#define GLAMOR_RESTORE_CONTEXT(glamor_priv) +static inline void +glamor_put_dispatch(glamor_screen_private *glamor_priv) +{ +} #endif diff --git a/glamor/glamor_window.c b/glamor/glamor_window.c index f6e4cd175..3da11e447 100644 --- a/glamor/glamor_window.c +++ b/glamor/glamor_window.c @@ -21,10 +21,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - #include "glamor_priv.h" /** @file glamor_window.c From 53387728ddc0c871821b68d728bb5f96a53ba227 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Feb 2012 17:40:37 +0800 Subject: [PATCH 303/462] glamor_tile/composite: Modify fs to re-calculate texture coords. Then we don't need to fixup the larger pixmap to the exact size, just need to let the shader to re-calculate the correct texture coords. Signed-off-by: Zhigang Gong --- glamor/glamor_gl_dispatch.c | 2 + glamor/glamor_gl_dispatch.h | 4 ++ glamor/glamor_priv.h | 3 ++ glamor/glamor_render.c | 80 +++++++++++++++++-------------------- glamor/glamor_tile.c | 24 ++++++----- 5 files changed, 61 insertions(+), 52 deletions(-) diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index da66380fb..ef0ac439a 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -66,6 +66,8 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glUseProgram, get_proc_address); INIT_FUNC(dispatch, glUniform1i, get_proc_address); INIT_FUNC(dispatch, glUniform4f, get_proc_address); + INIT_FUNC(dispatch, glUniform1fv, get_proc_address); + INIT_FUNC(dispatch, glUniform2fv, get_proc_address); INIT_FUNC(dispatch, glUniform4fv, get_proc_address); INIT_FUNC(dispatch, glCreateProgram, get_proc_address); INIT_FUNC(dispatch, glDeleteProgram, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index 024de265a..bd33bcc47 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -94,6 +94,10 @@ typedef struct glamor_gl_dispatch { void (*glUniform1i) (GLint location, GLint v0); void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void (*glUniform1fv) (GLint location, GLsizei count, + const GLfloat * value); + void (*glUniform2fv) (GLint location, GLsizei count, + const GLfloat * value); void (*glUniform4fv) (GLint location, GLsizei count, const GLfloat * value); GLuint(*glCreateProgram) (void); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 05bb18ac1..0d3aa82c3 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -64,6 +64,8 @@ typedef struct glamor_composite_shader { GLint dest_to_mask_uniform_location; GLint source_uniform_location; GLint mask_uniform_location; + GLint source_wh; + GLint mask_wh; } glamor_composite_shader; typedef struct { @@ -203,6 +205,7 @@ typedef struct glamor_screen_private { /* glamor_tile */ GLint tile_prog; + GLint tile_wh; /* glamor_putimage */ GLint put_image_xybitmap_prog; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 89e8265a8..7388192a8 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -70,6 +70,15 @@ static GLuint glamor_create_composite_fs(glamor_gl_dispatch * dispatch, struct shader_key *key) { + const char *relocate_texture = + GLAMOR_DEFAULT_PRECISION + "vec2 rel_tex_coord(vec2 texture, vec2 wh) \n" + "{\n" + " vec2 rel_tex; \n" + " rel_tex = texture * wh; \n" + " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n" + " return rel_tex; \n" + "}\n"; const char *source_solid_fetch = GLAMOR_DEFAULT_PRECISION "uniform vec4 source;\n" @@ -78,26 +87,35 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" + "uniform vec2 source_wh;" "vec4 get_source()\n" - "{\n" " return texture2D(source_sampler, source_texture);\n" + "{\n" " return texture2D(source_sampler, rel_tex_coord(source_texture, source_wh));\n" "}\n"; const char *source_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" - "uniform sampler2D source_sampler;\n" "vec4 get_source()\n" + "uniform sampler2D source_sampler;\n" + "uniform vec2 source_wh;" + "vec4 get_source()\n" "{\n" - " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" + " return vec4(texture2D(source_sampler, rel_tex_coord(source_texture, source_wh)).rgb, 1);\n" "}\n"; const char *mask_solid_fetch = GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" "vec4 get_mask()\n" "{\n" " return mask;\n" "}\n"; const char *mask_alpha_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" - "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" - " return texture2D(mask_sampler, mask_texture);\n" "}\n"; + "uniform sampler2D mask_sampler;\n" + "uniform vec2 mask_wh;" + "vec4 get_mask()\n" + "{\n" + " return texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh));\n" "}\n"; const char *mask_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" - "uniform sampler2D mask_sampler;\n" "vec4 get_mask()\n" "{\n" - " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" + "uniform sampler2D mask_sampler;\n" + "uniform vec2 mask_wh;" + "vec4 get_mask()\n" + "{\n" + " return vec4(texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh)).rgb, 1);\n" "}\n"; const char *in_source_only = GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" @@ -164,7 +182,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, FatalError("Bad composite IN type"); } - XNFasprintf(&source, "%s%s%s", source_fetch, mask_fetch, in); + XNFasprintf(&source, "%s%s%s%s", relocate_texture, source_fetch, mask_fetch, in); prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, @@ -255,6 +273,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, source_sampler_uniform_location = dispatch->glGetUniformLocation(prog, "source_sampler"); dispatch->glUniform1i(source_sampler_uniform_location, 0); + shader->source_wh = dispatch->glGetUniformLocation(prog, "source_wh"); } if (key->mask != SHADER_MASK_NONE) { @@ -267,6 +286,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, "mask_sampler"); dispatch->glUniform1i (mask_sampler_uniform_location, 1); + shader->mask_wh = dispatch->glGetUniformLocation(prog, "mask_wh"); } } @@ -449,36 +469,11 @@ glamor_set_composite_op(ScreenPtr screen, return TRUE; } -static void -glamor_composite_texture_fixup(ScreenPtr screen, - PicturePtr picture, - glamor_pixmap_private * pixmap_priv) -{ - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - Bool has_repeat; - int width, height; - - if (picture->repeatType == RepeatNone) - has_repeat = FALSE; - else - has_repeat = TRUE; - - if (has_repeat - && ( (pixmap_priv->container->drawable.width != pixmap_priv->fbo->width) - || (pixmap_priv->container->drawable.height != pixmap_priv->fbo->height))) { - /* Currently, we can't support repeat on partial texture, now redirect it - * to an exact size fbo. */ - DEBUGF("prepare to fixup texture \n"); - if (!glamor_fixup_pixmap_priv(screen, pixmap_priv)) - ErrorF("Failed to fixup a unmatch size of repeat picture. \n"); - } -} - static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, - glamor_pixmap_private * pixmap_priv) + glamor_pixmap_private * pixmap_priv, + GLuint wh_location) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -487,6 +482,8 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, dispatch = glamor_get_dispatch(glamor_priv); dispatch->glActiveTexture(GL_TEXTURE0 + unit); dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); + float wh[2]; + switch (picture->repeatType) { case RepeatNone: #ifndef GLAMOR_GLES2 @@ -539,6 +536,9 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif + wh[0] = (float)pixmap_priv->fbo->width / pixmap_priv->container->drawable.width; + wh[1] = (float)pixmap_priv->fbo->height / pixmap_priv->container->drawable.height; + dispatch->glUniform2fv(wh_location, 1, wh); glamor_put_dispatch(glamor_priv); } @@ -1081,12 +1081,6 @@ glamor_composite_with_shader(CARD8 op, } } #endif - - if (key.source != SHADER_SOURCE_SOLID) - glamor_composite_texture_fixup(screen, source, source_pixmap_priv); - if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) - glamor_composite_texture_fixup(screen, mask, mask_pixmap_priv); - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); glamor_validate_pixmap(dest_pixmap); @@ -1109,7 +1103,7 @@ glamor_composite_with_shader(CARD8 op, shader->source_uniform_location); } else { glamor_set_composite_texture(screen, 0, source, - source_pixmap_priv); + source_pixmap_priv, shader->source_wh); } if (key.mask != SHADER_MASK_NONE) { if (key.mask == SHADER_MASK_SOLID) { @@ -1118,7 +1112,7 @@ glamor_composite_with_shader(CARD8 op, shader->mask_uniform_location); } else { glamor_set_composite_texture(screen, 1, mask, - mask_pixmap_priv); + mask_pixmap_priv, shader->mask_wh); } } diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 917078fa2..aa62d095e 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -49,8 +49,13 @@ glamor_init_tile_shader(ScreenPtr screen) GLAMOR_DEFAULT_PRECISION "varying vec2 tile_texture;\n" "uniform sampler2D sampler;\n" + "uniform vec2 wh;" "void main()\n" - "{\n" " gl_FragColor = texture2D(sampler, tile_texture);\n" + "{\n" + " vec2 rel_tex;" + " rel_tex = tile_texture * wh; \n" + " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n" + " gl_FragColor = texture2D(sampler, rel_tex);\n" "}\n"; GLint fs_prog, vs_prog; GLint sampler_uniform_location; @@ -76,6 +81,10 @@ glamor_init_tile_shader(ScreenPtr screen) "sampler"); dispatch->glUseProgram(glamor_priv->tile_prog); dispatch->glUniform1i(sampler_uniform_location, 0); + + glamor_priv->tile_wh = + dispatch->glGetUniformLocation(glamor_priv->tile_prog, + "wh"); dispatch->glUseProgram(0); glamor_put_dispatch(glamor_priv); } @@ -115,6 +124,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; + float wh[2]; src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -142,14 +152,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, goto fail; } - if (src_pixmap_priv->fbo->width != tile->drawable.width - || src_pixmap_priv->fbo->height != tile->drawable.height) { - if (!glamor_fixup_pixmap_priv(screen, src_pixmap_priv)) { - glamor_fallback("Failed to create a fixup pixmap for partial tiling. \n"); - goto fail; - } - } - if (alu != GXcopy) { glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); glamor_validate_pixmap(tile); @@ -167,6 +169,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, &src_yscale); dispatch->glUseProgram(glamor_priv->tile_prog); + wh[0] = (float)src_pixmap_priv->fbo->width / tile->drawable.width; + wh[1] = (float)src_pixmap_priv->fbo->height / tile->drawable.height; + + dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->fbo->tex); From ce634e84d4bb559f01203653c5ffd6397f4b0366 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 12 Feb 2012 09:18:51 +0800 Subject: [PATCH 304/462] glamor_render: Only recalculate texture for repeat case. Slightly optimize the fragment shader, as if we are not repeat case and not exceed the valid texture range, then we don't need to recalculate the coords. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 7388192a8..9f0b03446 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -89,7 +89,11 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform sampler2D source_sampler;\n" "uniform vec2 source_wh;" "vec4 get_source()\n" - "{\n" " return texture2D(source_sampler, rel_tex_coord(source_texture, source_wh));\n" + "{\n" + " if (source_wh.x < 0.0) \n" + " return texture2D(source_sampler, source_texture);\n" + " else \n" + " return texture2D(source_sampler, rel_tex_coord(source_texture, source_wh));\n" "}\n"; const char *source_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" @@ -97,7 +101,10 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 source_wh;" "vec4 get_source()\n" "{\n" - " return vec4(texture2D(source_sampler, rel_tex_coord(source_texture, source_wh)).rgb, 1);\n" + " if (source_wh.x < 0.0) \n" + " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" + " else \n" + " return vec4(texture2D(source_sampler, rel_tex_coord(source_texture, source_wh)).rgb, 1);\n" "}\n"; const char *mask_solid_fetch = GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" @@ -108,14 +115,21 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 mask_wh;" "vec4 get_mask()\n" "{\n" - " return texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh));\n" "}\n"; + " if (mask_wh.x < 0.0) \n" + " return texture2D(mask_sampler, mask_texture);\n" + " else \n" + " return texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh));\n" + "}\n"; const char *mask_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" "uniform vec2 mask_wh;" "vec4 get_mask()\n" "{\n" - " return vec4(texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh)).rgb, 1);\n" + " if (mask_wh.x < 0.0) \n" + " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" + " else \n" + " return vec4(texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh)).rgb, 1);\n" "}\n"; const char *in_source_only = GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" @@ -483,6 +497,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, dispatch->glActiveTexture(GL_TEXTURE0 + unit); dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); float wh[2]; + Bool has_repeat; switch (picture->repeatType) { case RepeatNone: @@ -536,8 +551,17 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - wh[0] = (float)pixmap_priv->fbo->width / pixmap_priv->container->drawable.width; - wh[1] = (float)pixmap_priv->fbo->height / pixmap_priv->container->drawable.height; + if (picture->repeatType == RepeatNone) + has_repeat = picture->transform + && !pixman_transform_is_int_translate(picture->transform); + else + has_repeat = TRUE; + if (has_repeat) { + wh[0] = (float)pixmap_priv->fbo->width / pixmap_priv->container->drawable.width; + wh[1] = (float)pixmap_priv->fbo->height / pixmap_priv->container->drawable.height; + } + else + wh[0] = -1; dispatch->glUniform2fv(wh_location, 1, wh); glamor_put_dispatch(glamor_priv); } From 5ccf721d386a62f411d77bbc9a142e0c395162b3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 14 Feb 2012 17:39:11 +0800 Subject: [PATCH 305/462] glamor_fbo: Fix a bug when create No gl FBO pixmap. Need to get format before goto create a new fbo. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index e5675d81c..ec1a5b067 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -341,6 +341,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, || !glamor_check_fbo_depth(depth)) return NULL; + gl_iformat_for_depth(depth, &format); if (flag == GLAMOR_CREATE_FBO_NO_FBO) goto new_fbo; @@ -349,7 +350,6 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, else cache_flag = 0; - gl_iformat_for_depth(depth, &format); fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, format, cache_flag); if (fbo) From 8012b030c3144b02af036107179c5b4c94567292 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 17 Feb 2012 16:26:59 +0800 Subject: [PATCH 306/462] glamor_copyarea: Don't use GL_CLAMP_TO_BORDER when GLES2 enabled. We may need to modify all the shader to handle GL_CLAMP_TO_BORDER when using GLES2. XXX, for now, we just ignore them. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index de02224a3..87b53a983 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -219,6 +219,12 @@ glamor_copy_n_to_n_textured(DrawablePtr src, src_pixmap_priv->fbo->tex); #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_BORDER); #endif dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -226,12 +232,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_BORDER); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_BORDER); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, From 213285f2b8c6578e01783a77d954ccc3ec313663 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 17 Feb 2012 16:56:05 +0800 Subject: [PATCH 307/462] For DRI swap buffers. This commit added two APIs to support the DRI swap buffer. one is glamor_egl_exchange_buffers() which can swap two pixmaps' underlying KHRimages/fbos/texs. The DDX layer should exchange the DRM bos to make them consistent to each other. Another API is glamor_egl_create_textured_screen_ext(), which extent one more parameters to track the DDX layer's back pixmap pointer. This is for the triple buffer support. When using triple buffer, the DDX layer will keep a back pixmap rather then the front pixmap and the pixmap used by the DRI2 client. And during the closing screen stage, we have to dereference all the back pixmap's glamor resources. Thus we have to extent this API to register it when create new screen. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 34 ++++++++++++++++++++++--- glamor/glamor.h | 24 +++++++++++++++++- glamor/glamor_egl.c | 59 +++++++++++++++++++++++++++++++++++++++++--- glamor/glamor_fbo.c | 19 ++++++++++++++ glamor/glamor_priv.h | 12 ++------- 5 files changed, 129 insertions(+), 19 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 86de1154b..0d9ba2814 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -106,7 +106,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) } void -glamor_set_screen_pixmap(PixmapPtr screen_pixmap) +glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap) { glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; @@ -117,6 +117,8 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap) pixmap_priv->fbo->width = screen_pixmap->drawable.width; pixmap_priv->fbo->height = screen_pixmap->drawable.height; + + glamor_priv->back_pixmap = back_pixmap; } PixmapPtr @@ -420,6 +422,29 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_set_screen_private(screen, NULL); } +_X_EXPORT void +glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) +{ + glamor_pixmap_private *old_priv; + glamor_pixmap_fbo *fbo; + + old_priv = dixGetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); + + if (priv) { + assert(old_priv == NULL); + } else { + if (old_priv == NULL) + return; + fbo = glamor_pixmap_detach_fbo(old_priv); + glamor_purge_fbo(fbo); + free(old_priv); + } + + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, + priv); +} + Bool glamor_close_screen(int idx, ScreenPtr screen) { @@ -458,9 +483,10 @@ glamor_close_screen(int idx, ScreenPtr screen) } #endif screen_pixmap = screen->GetScreenPixmap(screen); - screen_pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - fbo = glamor_pixmap_detach_fbo(screen_pixmap_priv); - glamor_purge_fbo(fbo); + glamor_set_pixmap_private(screen_pixmap, NULL); + if (glamor_priv->back_pixmap && *glamor_priv->back_pixmap) + glamor_set_pixmap_private(*glamor_priv->back_pixmap, NULL); + glamor_release_screen_priv(screen); return screen->CloseScreen(idx, screen); diff --git a/glamor/glamor.h b/glamor/glamor.h index d3437d381..4a4e9bdcb 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -120,7 +120,7 @@ extern _X_EXPORT Bool glamor_close_screen(int idx, ScreenPtr screen); /* Let glamor to know the screen's fbo. The low level * driver should already assign a tex * to this pixmap through the set_pixmap_texture. */ -extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap); +extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap); /* @glamor_glyphs_init: Initialize glyphs internal data structures. * @@ -146,6 +146,16 @@ extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen); extern _X_EXPORT void glamor_egl_make_current(ScreenPtr screen); extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen); +/* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo). + * + * @front: front pixmap. + * @back: back pixmap. + * + * Used by the DRI2 page flip. This function will exchange the KHR images and + * fbos of the two pixmaps. + * */ +extern _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back); + #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" @@ -183,6 +193,18 @@ extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride); + +/* @glamor_egl_create_textured_screen_ext: + * + * extent one parameter to track the pointer of the DDX layer's back pixmap. + * We need this pointer during the closing screen stage. As before back to + * the DDX's close screen, we have to free all the glamor related resources. + */ +extern _X_EXPORT Bool glamor_egl_create_textured_screen_ext(ScreenPtr screen, + int handle, + int stride, + PixmapPtr *back_pixmap); + /* * @glamor_egl_create_textured_pixmap: Try to create a textured pixmap from * a BO handle. diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index ecbc186fa..081b363ab 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -85,6 +85,7 @@ struct glamor_egl_screen_private { CloseScreenProcPtr CloseScreen; int fd; EGLImageKHR front_image; + PixmapPtr *back_pixmap; int cpp; #ifdef GLAMOR_HAS_GBM struct gbm_device *gbm; @@ -233,7 +234,24 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) glamor_egl->front_image = dixLookupPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key); - glamor_set_screen_pixmap(screen_pixmap); + glamor_set_screen_pixmap(screen_pixmap, glamor_egl->back_pixmap); + return TRUE; +} + +Bool +glamor_egl_create_textured_screen_ext(ScreenPtr screen, + int handle, + int stride, + PixmapPtr *back_pixmap) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_egl_screen_private *glamor_egl; + + glamor_egl = glamor_egl_get_screen_private(scrn); + + glamor_egl->back_pixmap = back_pixmap; + if (!glamor_egl_create_textured_screen(screen, handle, stride)) + return FALSE; return TRUE; } @@ -280,9 +298,10 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) ((stride * 8 + 7) / pixmap->drawable.bitsPerPixel), name, pixmap->drawable.depth); - if (image == EGL_NO_IMAGE_KHR) + if (image == EGL_NO_IMAGE_KHR) { + glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); goto done; - + } glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, texture); @@ -315,6 +334,28 @@ _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) } } +extern void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back); + +_X_EXPORT void +glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) +{ + ScrnInfoPtr scrn = xf86Screens[front->drawable.pScreen->myNum]; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + EGLImageKHR old_front_image; + EGLImageKHR new_front_image; + + glamor_pixmap_exchange_fbos(front, back); + new_front_image = dixLookupPrivate(&back->devPrivates, glamor_egl_pixmap_private_key); + old_front_image = dixLookupPrivate(&front->devPrivates, glamor_egl_pixmap_private_key); + dixSetPrivate(&front->devPrivates, glamor_egl_pixmap_private_key, new_front_image); + dixSetPrivate(&back->devPrivates, glamor_egl_pixmap_private_key, old_front_image); + glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM); + glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); + glamor_egl->front_image = new_front_image; + +} + void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) { @@ -329,13 +370,24 @@ glamor_egl_close_screen(int idx, ScreenPtr screen) ScrnInfoPtr scrn; struct glamor_egl_screen_private *glamor_egl; PixmapPtr screen_pixmap; + EGLImageKHR back_image; scrn = xf86Screens[screen->myNum]; glamor_egl = glamor_egl_get_screen_private(scrn); screen_pixmap = screen->GetScreenPixmap(screen); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, glamor_egl->front_image); dixSetPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key, NULL); glamor_egl->front_image = NULL; + if (glamor_egl->back_pixmap && *glamor_egl->back_pixmap) { + back_image = dixLookupPrivate(&(*glamor_egl->back_pixmap)->devPrivates, + glamor_egl_pixmap_private_key); + if (back_image != NULL && back_image != EGL_NO_IMAGE_KHR) { + glamor_egl->egl_destroy_image_khr(glamor_egl->display, back_image); + dixSetPrivate(&(*glamor_egl->back_pixmap)->devPrivates, + glamor_egl_pixmap_private_key, NULL); + } + } screen->CloseScreen = glamor_egl->saved_close_screen; @@ -383,7 +435,6 @@ glamor_egl_free_screen(int scrnIndex, int flags) ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_egl_screen_private *glamor_egl; - ErrorF("free egl screen resources\n"); glamor_egl = glamor_egl_get_screen_private(scrn); if (glamor_egl != NULL) { diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index ec1a5b067..b4e4af71e 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -427,3 +427,22 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) break; } } +/* + * XXX how to handle those pending OPs. + * By default, pending OP is disabled. Maybe we will give up the pending + * OP latter. + * + * */ + +_X_EXPORT void +glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back) +{ + glamor_pixmap_private *front_priv, *back_priv; + glamor_pixmap_fbo *temp_fbo; + + front_priv = glamor_get_pixmap_private(front); + back_priv = glamor_get_pixmap_private(back); + temp_fbo = front_priv->fbo; + front_priv->fbo = back_priv->fbo; + back_priv->fbo = temp_fbo; +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0d3aa82c3..b9670a398 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -212,6 +212,7 @@ typedef struct glamor_screen_private { GLint put_image_xybitmap_fg_uniform_location; GLint put_image_xybitmap_bg_uniform_location; + PixmapPtr *back_pixmap; int screen_fbo; struct glamor_saved_procs saved_procs; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; @@ -344,16 +345,7 @@ glamor_get_pixmap_private(PixmapPtr pixmap) glamor_pixmap_private_key); } -static inline void -glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) -{ - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, - priv); -} - - - +void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv); /** * Returns TRUE if the given planemask covers all the significant bits in the From cd75e85ff36827b8438d965750faab0615d01e86 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Mon, 5 Mar 2012 08:24:20 +0800 Subject: [PATCH 308/462] Fixup For list.h change in xorg Because the file list.h in xorg/include has changed the functions and struct names, adding xorg_ prefix before the original name. So Modify glamor_screen_private struct and the code which use list's functions in glamor_fbo.c. We hack at glamor_priv.h avoid the compile error when using old version xserver header file. Signed-off-by: Junyan He --- glamor/glamor_fbo.c | 50 ++++++++++++++++++++++---------------------- glamor/glamor_priv.h | 20 +++++++++++++++--- 2 files changed, 42 insertions(+), 28 deletions(-) mode change 100644 => 100755 glamor/glamor_priv.h diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index b4e4af71e..3ae656250 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -9,13 +9,13 @@ #define GLAMOR_CACHE_TEXTURE 2 /* Loop from the tail to the head. */ -#define list_for_each_entry_reverse(pos, head, member) \ +#define xorg_list_for_each_entry_reverse(pos, head, member) \ for (pos = __container_of((head)->prev, pos, member); \ &pos->member != (head); \ pos = __container_of(pos->member.prev, pos, member)) -#define list_for_each_entry_safe_reverse(pos, tmp, head, member) \ +#define xorg_list_for_each_entry_safe_reverse(pos, tmp, head, member) \ for (pos = __container_of((head)->prev, pos, member), \ tmp = __container_of(pos->member.prev, pos, member); \ &pos->member != (head); \ @@ -77,7 +77,7 @@ glamor_pixmap_fbo * glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag) { - struct list *cache; + struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry; int size; @@ -90,27 +90,27 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, [cache_wbucket(w)] [cache_hbucket(h)]; if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) { - list_for_each_entry(fbo_entry, cache, list) { + xorg_list_for_each_entry(fbo_entry, cache, list) { if (fbo_entry->width >= w && fbo_entry->height >= h) { DEBUGF("Request w %d h %d \n", w, h); DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", fbo_entry, fbo_entry->width, fbo_entry->height, fbo_entry->fb, fbo_entry->tex); - list_del(&fbo_entry->list); + xorg_list_del(&fbo_entry->list); return fbo_entry; } } } else { - list_for_each_entry(fbo_entry, cache, list) { + xorg_list_for_each_entry(fbo_entry, cache, list) { if (fbo_entry->width == w && fbo_entry->height == h) { DEBUGF("Request w %d h %d \n", w, h); DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", fbo_entry, fbo_entry->width, fbo_entry->height, fbo_entry->fb, fbo_entry->tex); - list_del(&fbo_entry->list); + xorg_list_del(&fbo_entry->list); return fbo_entry; } } @@ -138,7 +138,7 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo) void glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) { - struct list *cache; + struct xorg_list *cache; if (fbo->fb == 0) { glamor_purge_fbo(fbo); @@ -155,7 +155,7 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) [cache_hbucket(fbo->height)]; DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); - list_add(&fbo->list, cache); + xorg_list_add(&fbo->list, cache); fbo->expire = fbo->glamor_priv->tick + GLAMOR_CACHE_EXPIRE_MAX; } @@ -170,7 +170,7 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, if (fbo == NULL) return NULL; - list_init(&fbo->list); + xorg_list_init(&fbo->list); gl_iformat_for_depth(depth, &format); fbo->tex = tex; @@ -189,7 +189,7 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, void glamor_fbo_expire(glamor_screen_private *glamor_priv) { - struct list *cache; + struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry, *tmp; int i,j,k; int empty_cache = TRUE; @@ -198,24 +198,24 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) for(j = 0; j < CACHE_BUCKET_WCOUNT; j++) for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) { cache = &glamor_priv->fbo_cache[i][j][k]; - list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { if (GLAMOR_TICK_AFTER(fbo_entry->expire, glamor_priv->tick)) { empty_cache = FALSE; break; } - list_del(&fbo_entry->list); + xorg_list_del(&fbo_entry->list); DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, fbo_entry->expire, glamor_priv->tick); glamor_purge_fbo(fbo_entry); } #if 0 cache = &glamor_priv->tex_cache[i][j][k]; - list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { if (GLAMOR_TICK_AFTER(fbo_entry->expire, glamor_priv->tick)) { empty_cache = FALSE; break; } - list_del(&fbo_entry->list); + xorg_list_del(&fbo_entry->list); DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, fbo_entry->expire, glamor_priv->tick); glamor_purge_fbo(fbo_entry); @@ -236,15 +236,15 @@ glamor_init_pixmap_fbo(ScreenPtr screen) for(j = 0; j < CACHE_BUCKET_WCOUNT; j++) for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) { - list_init(&glamor_priv->fbo_cache[i][j][k]); - list_init(&glamor_priv->tex_cache[i][j][k]); + xorg_list_init(&glamor_priv->fbo_cache[i][j][k]); + xorg_list_init(&glamor_priv->tex_cache[i][j][k]); } } void glamor_fini_pixmap_fbo(ScreenPtr screen) { - struct list *cache; + struct xorg_list *cache; glamor_screen_private *glamor_priv; glamor_pixmap_fbo *fbo_entry, *tmp; int i,j,k; @@ -255,14 +255,14 @@ glamor_fini_pixmap_fbo(ScreenPtr screen) for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) { cache = &glamor_priv->fbo_cache[i][j][k]; - list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { - list_del(&fbo_entry->list); + xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + xorg_list_del(&fbo_entry->list); glamor_purge_fbo(fbo_entry); } #if 0 cache = &glamor_priv->tex_cache[i][j][k]; - list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { - list_del(&fbo_entry->list); + xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { + xorg_list_del(&fbo_entry->list); glamor_purge_fbo(fbo_entry); } #endif @@ -272,7 +272,7 @@ glamor_fini_pixmap_fbo(ScreenPtr screen) void glamor_destroy_fbo(glamor_pixmap_fbo *fbo) { - list_del(&fbo->list); + xorg_list_del(&fbo->list); glamor_pixmap_fbo_cache_put(fbo); } @@ -297,7 +297,7 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, if (fbo == NULL) return NULL; - list_init(&fbo->list); + xorg_list_init(&fbo->list); dispatch = glamor_get_dispatch(glamor_priv); dispatch->glGenTextures(1, &tex); @@ -323,7 +323,7 @@ void glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) { assert(tex_obj->fb == 0); - list_del(&tex_obj->list); + xorg_list_del(&tex_obj->list); glamor_pixmap_fbo_cache_put(tex_obj); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h old mode 100644 new mode 100755 index b9670a398..1404703b9 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -56,6 +56,20 @@ #include "glamor_debug.h" #include +/* The list.h rename all the function to add xorg_ prefix. + We add hack here to avoid the compile error when using + old version xserver header file. + These will be removed in future. */ +#ifndef xorg_list_entry +#define xorg_list list +#define xorg_list_for_each_entry list_for_each_entry +#define xorg_list_for_each_entry_safe list_for_each_entry_safe +#define xorg_list_del list_del +#define xorg_list_add list_add +#define xorg_list_append list_append +#define xorg_list_init list_init +#endif + typedef struct glamor_composite_shader { GLuint prog; @@ -177,8 +191,8 @@ typedef struct glamor_screen_private { int has_fbo_blit; int max_fbo_size; - struct list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; - struct list tex_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; + struct xorg_list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; + struct xorg_list tex_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; /* glamor_solid */ GLint solid_prog; @@ -262,7 +276,7 @@ typedef union _glamor_pending_op { * @glamor_priv: point to glamor private data. */ typedef struct glamor_pixmap_fbo { - struct list list; + struct xorg_list list; unsigned int expire; unsigned char pbo_valid; GLuint tex; From a57bf66d492a0eec7b1f2a08b2f424835694e3fb Mon Sep 17 00:00:00 2001 From: Junyan He Date: Mon, 26 Mar 2012 13:51:13 +0800 Subject: [PATCH 309/462] glamor_utils: Add some assistant functions to compare pixmaps/pictures. Reviewed-by: Chris Wilson Reviewed-by: Zhigang Gong Signed-off-by: Zhigang Gong --- glamor/glamor_utils.h | 272 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 4a51ba59e..36cc9bdd8 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -664,6 +664,278 @@ static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); } +static inline void _glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2, + int x, int y, int w, int h, + PictFormatShort short_format, + int all, int diffs) +{ + int i, j; + unsigned char * p1 = pixmap1->devPrivate.ptr; + unsigned char * p2 = pixmap2->devPrivate.ptr; + int line_need_printed = 0; + int test_code = 0xAABBCCDD; + int little_endian = 0; + unsigned char *p_test; + int bpp = pixmap1->drawable.depth == 8 ? 1 : 4; + + assert(pixmap1->devKind == pixmap2->devKind); + int stride = pixmap1->devKind; + + ErrorF("stride:%d, width:%d, height:%d\n", stride, w, h); + + p1 = p1 + y * stride + x; + p2 = p2 + y * stride + x; + + if (all) { + for (i = 0; i < h; i++) { + ErrorF("line %3d: ", i); + + for (j = 0; j < stride; j++) { + if (j % bpp == 0) + ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]); + else + ErrorF("%2x:%2x ", p1[j], p2[j]); + } + + p1 += stride; + p2 += stride; + ErrorF("\n"); + } + } else { + if (short_format == PICT_a8r8g8b8) { + p_test = (unsigned char *) & test_code; + little_endian = (*p_test == 0xDD); + bpp = 4; + + for (i = 0; i < h; i++) { + line_need_printed = 0; + + for (j = 0; j < stride; j++) { + if (p1[j] != p2[j] && (p1[j] - p2[j] > diffs || p2[j] - p1[j] > diffs)) { + if (line_need_printed) { + if (little_endian) { + switch (j % 4) { + case 2: + ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + case 1: + ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + case 0: + ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + case 3: + ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + } + } else { + switch (j % 4) { + case 1: + ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + case 2: + ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + case 3: + ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + case 0: + ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j], p2[j]); + break; + } + } + } else { + line_need_printed = 1; + j = -1; + ErrorF("line %3d: ", i); + continue; + } + } + } + + p1 += stride; + p2 += stride; + ErrorF("\n"); + } + } //more format can be added here. + else { // the default format, just print. + for (i = 0; i < h; i++) { + line_need_printed = 0; + + for (j = 0; j < stride; j++) { + if (p1[j] != p2[j]) { + if (line_need_printed) { + ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]); + } else { + line_need_printed = 1; + j = -1; + ErrorF("line %3d: ", i); + continue; + } + } + } + + p1 += stride; + p2 += stride; + ErrorF("\n"); + } + } + } +} + +static inline void glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2, + int x, int y, int w, int h, int all, int diffs) +{ + assert(pixmap1->drawable.depth == pixmap2->drawable.depth); + + glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO); + glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO); + + _glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs); + + glamor_finish_access(&pixmap1->drawable, GLAMOR_ACCESS_RO); + glamor_finish_access(&pixmap2->drawable, GLAMOR_ACCESS_RO); +} + +/* This function is used to compare two pictures. + If the picture has no drawable, we use fb functions to generate it. */ +static inline void glamor_compare_pictures( ScreenPtr screen, + PicturePtr fst_picture, + PicturePtr snd_picture, + int x_source, int y_source, + int width, int height, + int all, int diffs) +{ + PixmapPtr fst_pixmap; + PixmapPtr snd_pixmap; + int fst_generated, snd_generated; + glamor_pixmap_private *fst_pixmap_priv; + glamor_pixmap_private *snd_pixmap_priv; + int error; + int fst_type = -1; + int snd_type = -1; // -1 represent has drawable. + + if (fst_picture->format != snd_picture->format) { + ErrorF("Different picture format can not compare!\n"); + return; + } + + if (!fst_picture->pDrawable) { + fst_type = fst_picture->pSourcePict->type; + } + + if (!snd_picture->pDrawable) { + snd_type = snd_picture->pSourcePict->type; + } + + if ((fst_type != -1) && (snd_type != -1) && (fst_type != snd_type)) { + ErrorF("Different picture type will never be same!\n"); + return; + } + + fst_generated = snd_generated = 0; + + if (!fst_picture->pDrawable) { + PicturePtr pixman_pic; + PixmapPtr pixmap = NULL; + PictFormatShort format; + + format = fst_picture->format; + + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_CPU); + + pixman_pic = CreatePicture(0, + &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), format), + 0, 0, serverClient, &error); + + fbComposite(PictOpSrc, fst_picture, NULL, pixman_pic, + x_source, y_source, + 0, 0, + 0, 0, + width, height); + + glamor_destroy_pixmap(pixmap); + + fst_picture = pixman_pic; + fst_generated = 1; + } + + if (!snd_picture->pDrawable) { + PicturePtr pixman_pic; + PixmapPtr pixmap = NULL; + PictFormatShort format; + + format = snd_picture->format; + + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_CPU); + + pixman_pic = CreatePicture(0, + &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), format), + 0, 0, serverClient, &error); + + fbComposite(PictOpSrc, snd_picture, NULL, pixman_pic, + x_source, y_source, + 0, 0, + 0, 0, + width, height); + + glamor_destroy_pixmap(pixmap); + + snd_picture = pixman_pic; + snd_generated = 1; + } + + fst_pixmap = glamor_get_drawable_pixmap(fst_picture->pDrawable); + snd_pixmap = glamor_get_drawable_pixmap(snd_picture->pDrawable); + + if (fst_pixmap->drawable.depth != snd_pixmap->drawable.depth) { + if (fst_generated) + glamor_destroy_picture(fst_picture); + if (snd_generated) + glamor_destroy_picture(snd_picture); + + ErrorF("Different pixmap depth can not compare!\n"); + return; + } + + glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO); + glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO); + + if ((fst_type == SourcePictTypeLinear) || + (fst_type == SourcePictTypeRadial) || + (fst_type == SourcePictTypeConical) || + (snd_type == SourcePictTypeLinear) || + (snd_type == SourcePictTypeRadial) || + (snd_type == SourcePictTypeConical)) { + x_source = y_source = 0; + } + + _glamor_compare_pixmaps(fst_pixmap, snd_pixmap, + x_source, y_source, + width, height, + fst_picture->format, all, diffs); + + glamor_finish_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO); + glamor_finish_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO); + + if (fst_generated) + glamor_destroy_picture(fst_picture); + if (snd_generated) + glamor_destroy_picture(snd_picture); + + return; +} + static inline void glamor_make_current(ScreenPtr screen) { glamor_egl_make_current(screen); From ccf5d7f52bae664f90d2c33c9fcff099a820575f Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 23 Mar 2012 04:05:48 +0800 Subject: [PATCH 310/462] Prepare for modification of gradient using shader. Prepare for modification of gradient using shader. The gradient pixmaps now is generated by pixman and we will replace them with shader. Add structure fields and dispatch functions which will be needed. Some auxiliary macro for vertex convert. Reviewed-by: Chris Wilson Reviewed-by: Zhigang Gong Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 ++ glamor/glamor_gl_dispatch.c | 4 +++- glamor/glamor_gl_dispatch.h | 15 +++++++++------ glamor/glamor_priv.h | 13 +++++++++++++ glamor/glamor_render.c | 22 ++++++++++++++++++++++ glamor/glamor_utils.h | 29 +++++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 7 deletions(-) mode change 100755 => 100644 glamor/glamor_priv.h diff --git a/glamor/glamor.c b/glamor/glamor.c index 0d9ba2814..532b9efae 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -389,6 +389,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_tile_shader(screen); glamor_init_putimage_shaders(screen); glamor_init_finish_access_shaders(screen); + glamor_init_gradient_shader(screen); glamor_pixmap_init(screen); glamor_priv->flags = flags; @@ -416,6 +417,7 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_fini_tile_shader(screen); glamor_fini_putimage_shaders(screen); glamor_fini_finish_access_shaders(screen); + glamor_fini_gradient_shader(screen); glamor_pixmap_fini(screen); free(glamor_priv); diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index ef0ac439a..fc3c5c0a9 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -65,10 +65,12 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glUseProgram, get_proc_address); INIT_FUNC(dispatch, glUniform1i, get_proc_address); + INIT_FUNC(dispatch, glUniform1f, get_proc_address); INIT_FUNC(dispatch, glUniform4f, get_proc_address); + INIT_FUNC(dispatch, glUniform4fv, get_proc_address); INIT_FUNC(dispatch, glUniform1fv, get_proc_address); INIT_FUNC(dispatch, glUniform2fv, get_proc_address); - INIT_FUNC(dispatch, glUniform4fv, get_proc_address); + INIT_FUNC(dispatch, glUniformMatrix3fv, get_proc_address); INIT_FUNC(dispatch, glCreateProgram, get_proc_address); INIT_FUNC(dispatch, glDeleteProgram, get_proc_address); INIT_FUNC(dispatch, glCreateShader, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index bd33bcc47..6adbde99a 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -60,7 +60,7 @@ typedef struct glamor_gl_dispatch { const GLvoid * data, GLenum usage); GLvoid *(*glMapBuffer) (GLenum target, GLenum access); GLvoid *(*glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); - GLboolean(*glUnmapBuffer) (GLenum target); + GLboolean (*glUnmapBuffer) (GLenum target); void (*glBindBuffer) (GLenum target, GLuint buffer); void (*glDeleteBuffers) (GLsizei n, const GLuint * buffers); @@ -71,7 +71,7 @@ typedef struct glamor_gl_dispatch { void (*glDeleteFramebuffers) (GLsizei n, const GLuint * framebuffers); void (*glGenFramebuffers) (GLsizei n, GLuint * framebuffers); - GLenum(*glCheckFramebufferStatus) (GLenum target); + GLenum (*glCheckFramebufferStatus) (GLenum target); void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, @@ -92,6 +92,7 @@ typedef struct glamor_gl_dispatch { const GLint * length); void (*glUseProgram) (GLuint program); void (*glUniform1i) (GLint location, GLint v0); + void (*glUniform1f) (GLint location, GLfloat v0); void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); void (*glUniform1fv) (GLint location, GLsizei count, @@ -100,9 +101,11 @@ typedef struct glamor_gl_dispatch { const GLfloat * value); void (*glUniform4fv) (GLint location, GLsizei count, const GLfloat * value); - GLuint(*glCreateProgram) (void); - GLuint(*glDeleteProgram) (GLuint); - GLuint(*glCreateShader) (GLenum type); + void (*glUniformMatrix3fv) (GLint location, GLsizei count, + GLboolean transpose, const GLfloat* value); + GLuint (*glCreateProgram) (void); + GLuint (*glDeleteProgram) (GLuint); + GLuint (*glCreateShader) (GLenum type); void (*glCompileShader) (GLuint shader); void (*glAttachShader) (GLuint program, GLuint shader); void (*glGetShaderiv) (GLuint shader, GLenum pname, @@ -113,7 +116,7 @@ typedef struct glamor_gl_dispatch { GLint * params); void (*glGetProgramInfoLog) (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); - GLint(*glGetUniformLocation) (GLuint program, + GLint (*glGetUniformLocation) (GLuint program, const GLchar * name); } glamor_gl_dispatch; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h old mode 100755 new mode 100644 index 1404703b9..ad6873757 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -123,6 +123,13 @@ enum shader_in { SHADER_IN_COUNT, }; +enum gradient_shader_type { + GRADIENT_SHADER_LINEAR, + GRADIENT_SHADER_RADIAL, + GRADIENT_SHADER_CONICAL, + GRADIENT_SHADER_COUNT, +}; + struct glamor_screen_private; struct glamor_pixmap_private; typedef void (*glamor_pixmap_validate_function_t) (struct @@ -221,6 +228,9 @@ typedef struct glamor_screen_private { GLint tile_prog; GLint tile_wh; + /* glamor gradient */ + GLint gradient_prog[GRADIENT_SHADER_COUNT]; + /* glamor_putimage */ GLint put_image_xybitmap_prog; GLint put_image_xybitmap_fg_uniform_location; @@ -562,6 +572,9 @@ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, void glamor_init_tile_shader(ScreenPtr screen); void glamor_fini_tile_shader(ScreenPtr screen); +void glamor_init_gradient_shader(ScreenPtr screen); +void glamor_fini_gradient_shader(ScreenPtr screen); + /* glamor_triangles.c */ void diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 9f0b03446..093e01ddf 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1275,6 +1275,28 @@ done: return ret; } + +void +glamor_init_gradient_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + + glamor_priv = glamor_get_screen_private(screen); + +} + +void +glamor_fini_gradient_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + glamor_put_dispatch(glamor_priv); +} + static PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr source, diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 36cc9bdd8..75ebc7ed9 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -99,6 +99,24 @@ (vertices)[7] = (vertices)[5]; \ } while(0) +#define glamor_set_tcoords(x1, y1, x2, y2, yInverted, vertices) \ + do { \ + (vertices)[0] = (x1); \ + (vertices)[2] = (x2); \ + (vertices)[4] = (vertices)[2]; \ + (vertices)[6] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = (y1); \ + (vertices)[5] = (y2); \ + } \ + else { \ + (vertices)[1] = (y2); \ + (vertices)[5] = (y1); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[7] = (vertices)[5]; \ + } while(0) + #define glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, \ yInverted, vertices) \ @@ -119,6 +137,17 @@ (vertices)[7] = (vertices)[5]; \ } while(0) +#define glamor_set_normalize_pt(xscale, yscale, x, x_start, y, y_start, \ + yInverted, pt) \ + do { \ + (pt)[0] = t_from_x_coord_x(xscale, x - x_start); \ + if (yInverted) { \ + (pt)[1] = t_from_x_coord_y_inverted(yscale, y - y_start); \ + } else { \ + (pt)[1] = t_from_x_coord_y(yscale, y - y_start); \ + } \ + (pt)[2] = (pt)[3] = 0.0; \ + } while(0) inline static void glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) From 1026327cdc90bc0c801a493b7b76b3efc5f33fe2 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 23 Mar 2012 04:05:56 +0800 Subject: [PATCH 311/462] Add the feature of generating linear gradient picture by using shader. Add the feature of generating linear gradient picture by using shader. This logic will replace the original linear gradient picture generating manner in glamor which firstly use pixman and then upload it to GPU. Compare it to the result generated by pixman, the difference of each color component of each pixel is normally 0, sometimes 1/255, and 2/255 at most. The pixman use fixed-point but shader use float-point, so may have difference. The feature of transform matrix and 4 types of repeat modes have been supported. The array usage in shader seems slow, so use 8 uniform variables to avoid using array when stops number is not very big. This make code look verbose but the performance improved a lot. We still have slightly performance regression compare to original pixman version. There are one further optimization opportunity which is to merge the gradient pixmap generation and the latter compositing into one shader, then we don't need to generate the extra texture, we can use the gradient value directly at the compositing shader. Hope that can beat pixman version. Will do that latter. Reviewed-by: Chris Wilson Reviewed-by: Zhigang Gong Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 978 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 968 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 093e01ddf..6304167ea 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1275,6 +1275,378 @@ done: return ret; } +static GLint +_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int use_array) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + GLint gradient_prog = 0; + char *gradient_fs = NULL; + GLint fs_prog, vs_prog; + + const char *gradient_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" + "}\n"; + + /* + * | + * |\ + * | \ + * | \ + * | \ + * |\ \ + * | \ \ + * cos_val = |\ p1d \ / + * sqrt(1/(slope*slope+1.0)) ------>\ \ \ / + * | \ \ \ + * | \ \ / \ + * | \ *Pt1\ + * *p1 | \ \ *P + * \ | / \ \ / + * \ | / \ \ / + * \ | pd \ + * \ | \ / \ + * p2* | \ / \ / + * slope = (p2.y - p1.y) / | / p2d / + * (p2.x - p1.x) | / \ / + * | / \ / + * | / / + * | / / + * | / *Pt2 + * | / + * | / + * | / + * | / + * | / + * -------+--------------------------------- + * O| + * | + * | + * + * step 1: compute the distance of p, pt1 and pt2 in the slope direction. + * Caculate the distance on Y axis first and multiply cos_val to + * get the value on slope direction(pd, p1d and p2d represent the + * distance of p, pt1, and pt2 respectively). + * + * step 2: caculate the percentage of (pd - p1d)/(p2d - p1d). + * If (pd - p1d) > (p2d - p1d) or < 0, then sub or add (p2d - p1d) + * to make it in the range of [0, (p2d - p1d)]. + * + * step 3: compare the percentage to every stop and find the stpos just + * before and after it. Use the interpolation fomula to compute RGBA. + */ + + const char *gradient_fs_template = + GLAMOR_DEFAULT_PRECISION + "uniform mat3 transform_mat;\n" + "uniform int repeat_type;\n" + "uniform int hor_ver;\n" + "uniform int n_stop;\n" + "uniform float stops[%d];\n" + "uniform vec4 stop_colors[%d];\n" + "uniform vec4 pt1;\n" + "uniform vec4 pt2;\n" + "uniform float pt_slope;\n" + "uniform float cos_val;\n" + "uniform float p1_distance;\n" + "uniform float pt_distance;\n" + "varying vec2 source_texture;\n" + "\n" + "vec4 get_color()\n" + "{\n" + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" + " float len_percentage;\n" + " float distance;\n" + " float _p1_distance;\n" + " float _pt_distance;\n" + " float y_dist;\n" + " float new_alpha; \n" + " int i = n_stop - 1;\n" + " int revserse = 0;\n" + " vec4 gradient_color;\n" + " float percentage; \n" + " vec3 source_texture_trans = transform_mat * tmp;\n" + " \n" + " if(hor_ver == 0) { \n" //Normal case. + " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n" + " distance = y_dist * cos_val;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " \n" + " } else if (hor_ver == 1) {\n"//horizontal case. + " distance = source_texture_trans.x;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " } else if (hor_ver == 2) {\n"//vertical case. + " distance = source_texture_trans.y;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " } \n" + " \n" + " distance = distance - _p1_distance; \n" + " \n" + " if(repeat_type == %d){\n" // repeat normal + " while(distance > _pt_distance) \n" + " distance = distance - (_pt_distance); \n" + " while(distance < 0.0) \n" + " distance = distance + (_pt_distance); \n" + " }\n" + " \n" + " if(repeat_type == %d) {\n" // repeat reflect + " while(distance > _pt_distance) {\n" + " distance = distance - (_pt_distance); \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " while(distance < 0.0) {\n" + " distance = distance + (_pt_distance); \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " if(revserse == 1) {\n" + " distance = (_pt_distance) - distance; \n" + " }\n" + " }\n" + " \n" + " len_percentage = distance/(_pt_distance);\n" + " for(i = 0; i < n_stop - 1; i++) {\n" + " if(len_percentage < stops[i])\n" + " break; \n" + " }\n" + " \n" + " percentage = (len_percentage - stops[i-1])/(stops[i] - stops[i-1]);\n" + " if(stops[i] - stops[i-1] > 2.0)\n" + " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. + " new_alpha = percentage * stop_colors[i].a + \n" + " (1.0-percentage) * stop_colors[i-1].a; \n" + " gradient_color = vec4((percentage * stop_colors[i].rgb \n" + " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" + " return gradient_color;\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = get_color();\n" + "}\n"; + + /* Because the array access for shader is very slow, the performance is very low + if use array. So use global uniform to replace for it if the number of n_stops is small.*/ + const char *gradient_fs_no_array_template = + GLAMOR_DEFAULT_PRECISION + "uniform mat3 transform_mat;\n" + "uniform int repeat_type;\n" + "uniform int hor_ver;\n" + "uniform int n_stop;\n" + "uniform float stop0;\n" + "uniform float stop1;\n" + "uniform float stop2;\n" + "uniform float stop3;\n" + "uniform float stop4;\n" + "uniform float stop5;\n" + "uniform float stop6;\n" + "uniform float stop7;\n" + "uniform vec4 stop_color0;\n" + "uniform vec4 stop_color1;\n" + "uniform vec4 stop_color2;\n" + "uniform vec4 stop_color3;\n" + "uniform vec4 stop_color4;\n" + "uniform vec4 stop_color5;\n" + "uniform vec4 stop_color6;\n" + "uniform vec4 stop_color7;\n" + "uniform vec4 pt1;\n" + "uniform vec4 pt2;\n" + "uniform float pt_slope;\n" + "uniform float cos_val;\n" + "uniform float p1_distance;\n" + "uniform float pt_distance;\n" + "varying vec2 source_texture;\n" + "\n" + "vec4 get_color()\n" + "{\n" + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" + " float len_percentage;\n" + " float distance;\n" + " float _p1_distance;\n" + " float _pt_distance;\n" + " float y_dist;\n" + " float stop_after;\n" + " float stop_before;\n" + " vec4 stop_color_before;\n" + " vec4 stop_color_after;\n" + " float new_alpha; \n" + " int revserse = 0;\n" + " vec4 gradient_color;\n" + " float percentage; \n" + " vec3 source_texture_trans = transform_mat * tmp;\n" + " \n" + " if(hor_ver == 0) { \n" //Normal case. + " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n" + " distance = y_dist * cos_val;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " \n" + " } else if (hor_ver == 1) {\n"//horizontal case. + " distance = source_texture_trans.x;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " } else if (hor_ver == 2) {\n"//vertical case. + " distance = source_texture_trans.y;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " } \n" + " \n" + " distance = distance - _p1_distance; \n" + " \n" + " if(repeat_type == %d){\n" // repeat normal + " while(distance > _pt_distance) \n" + " distance = distance - (_pt_distance); \n" + " while(distance < 0.0) \n" + " distance = distance + (_pt_distance); \n" + " }\n" + " \n" + " if(repeat_type == %d) {\n" // repeat reflect + " while(distance > _pt_distance) {\n" + " distance = distance - (_pt_distance); \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " while(distance < 0.0) {\n" + " distance = distance + (_pt_distance); \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " if(revserse == 1) {\n" + " distance = (_pt_distance) - distance; \n" + " }\n" + " }\n" + " \n" + " len_percentage = distance/(_pt_distance);\n" + " if((len_percentage < stop0) && (n_stop >= 1)) {\n" + " stop_color_before = stop_color0;\n" + " stop_color_after = stop_color0;\n" + " stop_after = stop0;\n" + " stop_before = stop0;\n" + " percentage = 0.0;\n" + " } else if((len_percentage < stop1) && (n_stop >= 2)) {\n" + " stop_color_before = stop_color0;\n" + " stop_color_after = stop_color1;\n" + " stop_after = stop1;\n" + " stop_before = stop0;\n" + " percentage = (len_percentage - stop0)/(stop1 - stop0);\n" + " } else if((len_percentage < stop2) && (n_stop >= 3)) {\n" + " stop_color_before = stop_color1;\n" + " stop_color_after = stop_color2;\n" + " stop_after = stop2;\n" + " stop_before = stop1;\n" + " percentage = (len_percentage - stop1)/(stop2 - stop1);\n" + " } else if((len_percentage < stop3) && (n_stop >= 4)){\n" + " stop_color_before = stop_color2;\n" + " stop_color_after = stop_color3;\n" + " stop_after = stop3;\n" + " stop_before = stop2;\n" + " percentage = (len_percentage - stop2)/(stop3 - stop2);\n" + " } else if((len_percentage < stop4) && (n_stop >= 5)){\n" + " stop_color_before = stop_color3;\n" + " stop_color_after = stop_color4;\n" + " stop_after = stop4;\n" + " stop_before = stop3;\n" + " percentage = (len_percentage - stop3)/(stop4 - stop3);\n" + " } else if((len_percentage < stop5) && (n_stop >= 6)){\n" + " stop_color_before = stop_color4;\n" + " stop_color_after = stop_color5;\n" + " stop_after = stop5;\n" + " stop_before = stop4;\n" + " percentage = (len_percentage - stop4)/(stop5 - stop4);\n" + " } else if((len_percentage < stop6) && (n_stop >= 7)){\n" + " stop_color_before = stop_color5;\n" + " stop_color_after = stop_color6;\n" + " stop_after = stop6;\n" + " stop_before = stop5;\n" + " percentage = (len_percentage - stop5)/(stop6 - stop5);\n" + " } else if((len_percentage < stop7) && (n_stop >= 8)){\n" + " stop_color_before = stop_color6;\n" + " stop_color_after = stop_color7;\n" + " stop_after = stop7;\n" + " stop_before = stop6;\n" + " percentage = (len_percentage - stop6)/(stop7 - stop6);\n" + " } else {\n" + " stop_color_before = stop_color7;\n" + " stop_color_after = stop_color7;\n" + " stop_after = stop7;\n" + " stop_before = stop7;\n" + " percentage = 0.0;\n" + " }\n" + " if(stop_after - stop_before > 2.0)\n" + " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. + " new_alpha = percentage * stop_color_after.a + \n" + " (1.0-percentage) * stop_color_before.a; \n" + " gradient_color = vec4((percentage * stop_color_after.rgb \n" + " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" + " return gradient_color;\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = get_color();\n" + "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + gradient_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, + GL_VERTEX_SHADER, gradient_vs); + + if (use_array) { + XNFasprintf(&gradient_fs, + gradient_fs_template, stops_count, stops_count, + PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + } else { + XNFasprintf(&gradient_fs, + gradient_fs_no_array_template, + PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + } + fs_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); + free(gradient_fs); + + dispatch->glAttachShader(gradient_prog, vs_prog); + dispatch->glAttachShader(gradient_prog, fs_prog); + + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); + + glamor_link_glsl_prog(dispatch, gradient_prog); + + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); + return gradient_prog; +} + +#define LINEAR_DEFAULT_STOPS 6 + 2 void glamor_init_gradient_shader(ScreenPtr screen) @@ -1283,6 +1655,9 @@ glamor_init_gradient_shader(ScreenPtr screen) glamor_priv = glamor_get_screen_private(screen); + glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR] = + _glamor_create_linear_gradient_program(screen, + LINEAR_DEFAULT_STOPS, 0); } void @@ -1294,17 +1669,584 @@ glamor_fini_gradient_shader(ScreenPtr screen) glamor_priv = glamor_get_screen_private(screen); dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glDeleteProgram( + glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR]); + glamor_put_dispatch(glamor_priv); } +static void +_glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], + int width, int height) +{ + /* + * Because in the shader program, we normalize all the pixel cood to [0, 1], + * so with the transform matrix, the correct logic should be: + * v_s = A*T*v + * v_s: point vector in shader after normalized. + * A: The transition matrix from width X height --> 1.0 X 1.0 + * T: The transform matrix. + * v: point vector in width X height space. + * + * result is OK if we use this fomula. But for every point in width X height space, + * we can just use their normalized point vector in shader, namely we can just + * use the result of A*v in shader. So we have no chance to insert T in A*v. + * We can just convert v_s = A*T*v to v_s = A*T*inv(A)*A*v, where inv(A) is the + * inverse matrix of A. Now, v_s = (A*T*inv(A)) * (A*v) + * So, to get the correct v_s, we need to cacula1 the matrix: (A*T*inv(A)), and + * we name this matrix T_s. + * + * Firstly, because A is for the scale convertion, we find + * -- -- + * |1/w 0 0 | + * A = | 0 1/h 0 | + * | 0 0 1.0| + * -- -- + * so T_s = A*T*inv(a) and result + * + * -- -- + * | t11 h*t12/w t13/w| + * T_s = | w*t21/h t22 t23/h| + * | w*t31 h*t32 t33 | + * -- -- + */ + + to[0][0] = (float)pixman_fixed_to_double(from->matrix[0][0]); + to[0][1] = (float)pixman_fixed_to_double(from->matrix[0][1]) + * ((float)height) / ((float)width); + to[0][2] = (float)pixman_fixed_to_double(from->matrix[0][2]) + / ((float)width); + + to[1][0] = (float)pixman_fixed_to_double(from->matrix[1][0]) + * ((float)width) / ((float)height); + to[1][1] = (float)pixman_fixed_to_double(from->matrix[1][1]); + to[1][2] = (float)pixman_fixed_to_double(from->matrix[1][2]) + / ((float)height); + + to[2][0] = (float)pixman_fixed_to_double(from->matrix[2][0]) + * ((float)width); + to[2][1] = (float)pixman_fixed_to_double(from->matrix[2][1]) + * ((float)height); + to[2][2] = (float)pixman_fixed_to_double(from->matrix[2][2]); + + DEBUGF("the transform matrix is:\n%f\t%f\t%f\n%f\t%f\t%f\n%f\t%f\t%f\n", + to[0][0], to[0][1], to[0][2], + to[1][0], to[1][1], to[1][2], + to[2][0], to[2][1], to[2][2]); +} + +static int +_glamor_gradient_set_pixmap_destination(ScreenPtr screen, + glamor_screen_private *glamor_priv, + PicturePtr dst_picure, + GLfloat *xscale, GLfloat *yscale, + int x_source, int y_source, + float vertices[8], + float tex_vertices[8], + int tex_normalize) +{ + glamor_pixmap_private *pixmap_priv; + PixmapPtr pixmap = NULL; + + pixmap = glamor_get_drawable_pixmap(dst_picure->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ + return 0; + } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + pixmap_priv_get_scale(pixmap_priv, xscale, yscale); + + glamor_priv->has_source_coords = 1; + glamor_priv->has_mask_coords = 0; + glamor_setup_composite_vbo(screen, 4*2); + + DEBUGF("xscale = %f, yscale = %f," + " x_source = %d, y_source = %d, width = %d, height = %d\n", + *xscale, *yscale, x_source, y_source, + pixmap_priv->fbo->width, pixmap_priv->fbo->height); + + glamor_set_normalize_vcoords(*xscale, *yscale, + 0, 0, + (INT16)(pixmap_priv->fbo->width), + (INT16)(pixmap_priv->fbo->height), + glamor_priv->yInverted, vertices); + + if (tex_normalize) { + glamor_set_normalize_tcoords(*xscale, *yscale, + 0, 0, + (INT16)(pixmap_priv->fbo->width), + (INT16)(pixmap_priv->fbo->height), + glamor_priv->yInverted, tex_vertices); + } else { + glamor_set_tcoords(0, 0, + (INT16)(pixmap_priv->fbo->width), + (INT16)(pixmap_priv->fbo->height), + glamor_priv->yInverted, tex_vertices); + } + + DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + vertices[0], vertices[1], vertices[2], vertices[3], + vertices[4], vertices[5], vertices[6], vertices[7]); + DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], + tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); + + return 1; +} + +static int +_glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, + GLfloat *stop_colors, GLfloat *n_stops) +{ + int i; + int count; + + for (i = 1; i < pgradient->nstops + 1; i++) { + stop_colors[i*4] = pixman_fixed_to_double( + pgradient->stops[i-1].color.red); + stop_colors[i*4+1] = pixman_fixed_to_double( + pgradient->stops[i-1].color.green); + stop_colors[i*4+2] = pixman_fixed_to_double( + pgradient->stops[i-1].color.blue); + stop_colors[i*4+3] = pixman_fixed_to_double( + pgradient->stops[i-1].color.alpha); + + n_stops[i] = (GLfloat)pixman_fixed_to_double( + pgradient->stops[i-1].x); + } + + count = pgradient->nstops + 2; + + switch (src_picture->repeatType) { +#define REPEAT_FILL_STOPS(m, n) \ + stop_colors[(m)*4 + 0] = stop_colors[(n)*4 + 0]; \ + stop_colors[(m)*4 + 1] = stop_colors[(n)*4 + 1]; \ + stop_colors[(m)*4 + 2] = stop_colors[(n)*4 + 2]; \ + stop_colors[(m)*4 + 3] = stop_colors[(n)*4 + 3]; + + default: + case PIXMAN_REPEAT_NONE: + stop_colors[0] = 0.0; //R + stop_colors[1] = 0.0; //G + stop_colors[2] = 0.0; //B + stop_colors[3] = 0.0; //Alpha + n_stops[0] = -(float)INT_MAX; //should be small enough. + + stop_colors[0 + (count-1)*4] = 0.0; //R + stop_colors[1 + (count-1)*4] = 0.0; //G + stop_colors[2 + (count-1)*4] = 0.0; //B + stop_colors[3 + (count-1)*4] = 0.0; //Alpha + n_stops[count-1] = (float)INT_MAX; //should be large enough. + break; + case PIXMAN_REPEAT_NORMAL: + REPEAT_FILL_STOPS(0, count - 2); + n_stops[0] = n_stops[count-2] - 1.0; + + REPEAT_FILL_STOPS(count - 1, 1); + n_stops[count-1] = n_stops[1] + 1.0; + break; + case PIXMAN_REPEAT_REFLECT: + REPEAT_FILL_STOPS(0, 1); + n_stops[0] = -n_stops[1]; + + REPEAT_FILL_STOPS(count - 1, count - 2); + n_stops[count-1] = 1.0 + 1.0 - n_stops[count-2]; + break; + case PIXMAN_REPEAT_PAD: + REPEAT_FILL_STOPS(0, 1); + n_stops[0] = -(float)INT_MAX; + + REPEAT_FILL_STOPS(count - 1, count - 2); + n_stops[count-1] = (float)INT_MAX; + break; +#undef REPEAT_FILL_STOPS + } + + for (i = 0; i < count; i++) { + DEBUGF("n_stops[%d] = %f, color = r:%f g:%f b:%f a:%f\n", + i, n_stops[i], + stop_colors[i*4], stop_colors[i*4+1], + stop_colors[i*4+2], stop_colors[i*4+3]); + } + + return count; +} + +static PicturePtr +_glamor_generate_linear_gradient_picture(ScreenPtr screen, + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + PicturePtr dst_picture = NULL; + PixmapPtr pixmap = NULL; + GLint gradient_prog = 0; + int error; + float pt_distance; + float p1_distance; + GLfloat cos_val; + float tex_vertices[8]; + int stops_count; + GLfloat *stop_colors = NULL; + GLfloat *n_stops = NULL; + int i = 0; + int count = 0; + float slope; + GLfloat xscale, yscale; + GLfloat pt1[4], pt2[4]; + float vertices[8]; + float transform_mat[3][3]; + static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}}; + GLfloat stop_colors_st[LINEAR_DEFAULT_STOPS*4]; + GLfloat n_stops_st[LINEAR_DEFAULT_STOPS]; + + GLint transform_mat_uniform_location; + GLint pt1_uniform_location; + GLint pt2_uniform_location; + GLint n_stop_uniform_location; + GLint stops_uniform_location; + GLint stop0_uniform_location; + GLint stop1_uniform_location; + GLint stop2_uniform_location; + GLint stop3_uniform_location; + GLint stop4_uniform_location; + GLint stop5_uniform_location; + GLint stop6_uniform_location; + GLint stop7_uniform_location; + GLint stop_colors_uniform_location; + GLint stop_color0_uniform_location; + GLint stop_color1_uniform_location; + GLint stop_color2_uniform_location; + GLint stop_color3_uniform_location; + GLint stop_color4_uniform_location; + GLint stop_color5_uniform_location; + GLint stop_color6_uniform_location; + GLint stop_color7_uniform_location; + GLint pt_slope_uniform_location; + GLint repeat_type_uniform_location; + GLint hor_ver_uniform_location; + GLint cos_val_uniform_location; + GLint p1_distance_uniform_location; + GLint pt_distance_uniform_location; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + /* Create a pixmap with VBO. */ + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_FIXUP); + + if (!pixmap) + goto GRADIENT_FAIL; + + dst_picture = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), format), + 0, 0, serverClient, &error); + + /* Release the reference, picture will hold the last one. */ + glamor_destroy_pixmap(pixmap); + + if (!dst_picture) + goto GRADIENT_FAIL; + + ValidatePicture(dst_picture); + + stops_count = src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS ? + src_picture->pSourcePict->linear.nstops + 2 : LINEAR_DEFAULT_STOPS; + + /* Because the max value of nstops is unkown, so create a program + when nstops > default.*/ + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + gradient_prog = glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR]; + } else { + gradient_prog = _glamor_create_linear_gradient_program(screen, + src_picture->pSourcePict->linear.nstops + 2, 1); + } + + /* Bind all the uniform vars .*/ + pt1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt1"); + pt2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt2"); + n_stop_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "n_stop"); + pt_slope_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt_slope"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + hor_ver_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "hor_ver"); + transform_mat_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); + cos_val_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "cos_val"); + p1_distance_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "p1_distance"); + pt_distance_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt_distance"); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + stop0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop0"); + stop1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop1"); + stop2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop2"); + stop3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop3"); + stop4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop4"); + stop5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop5"); + stop6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop6"); + stop7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop7"); + + stop_color0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); + stop_color1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); + stop_color2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); + stop_color3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); + stop_color4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); + stop_color5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); + stop_color6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); + stop_color7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); + } else { + stops_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stops"); + stop_colors_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); + } + + dispatch->glUseProgram(gradient_prog); + + dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); + + if (src_picture->transform) { + _glamor_gradient_convert_trans_matrix(src_picture->transform, + transform_mat, + width, height); + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &transform_mat[0][0]); + } else { + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &identity_mat[0][0]); + } + + if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, + &xscale, &yscale, x_source, y_source, + vertices, tex_vertices, 1)) + goto GRADIENT_FAIL; + + /* Normalize the PTs. */ + glamor_set_normalize_pt(xscale, yscale, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.x), + x_source, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.y), + y_source, + glamor_priv->yInverted, + pt1); + dispatch->glUniform4fv(pt1_uniform_location, 1, pt1); + DEBUGF("pt1:(%f %f)\n", pt1[0], pt1[1]); + + glamor_set_normalize_pt(xscale, yscale, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.x), + x_source, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.y), + y_source, + glamor_priv->yInverted, + pt2); + dispatch->glUniform4fv(pt2_uniform_location, 1, pt2); + DEBUGF("pt2:(%f %f)\n", pt2[0], pt2[1]); + + /* Set all the stops and colors to shader. */ + if (stops_count > LINEAR_DEFAULT_STOPS) { + stop_colors = malloc(4 * stops_count * sizeof(float)); + if (stop_colors == NULL) { + ErrorF("Failed to allocate stop_colors memory.\n"); + goto GRADIENT_FAIL; + } + + n_stops = malloc(stops_count * sizeof(float)); + if (n_stops == NULL) { + ErrorF("Failed to allocate n_stops memory.\n"); + goto GRADIENT_FAIL; + } + } else { + stop_colors = stop_colors_st; + n_stops = n_stops_st; + } + + count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, + stop_colors, n_stops); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + int j = 0; + dispatch->glUniform4f(stop_color0_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color1_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color2_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color3_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color4_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color5_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color6_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color7_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + + j = 0; + dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); + + dispatch->glUniform1i(n_stop_uniform_location, count); + } else { + dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); + dispatch->glUniform1fv(stops_uniform_location, count, n_stops); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + + if ((pt2[1] - pt1[1]) / yscale < 1.0) { // The horizontal case. + dispatch->glUniform1i(hor_ver_uniform_location, 1); + DEBUGF("p1.x: %f, p2.x: %f, enter the horizontal case\n", pt1[1], pt2[1]); + + p1_distance = pt1[0]; + pt_distance = (pt2[0] - p1_distance); + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } else if ((pt2[0] - pt1[0]) / xscale < 1.0) { //The vertical case. + dispatch->glUniform1i(hor_ver_uniform_location, 2); + DEBUGF("p1.y: %f, p2.y: %f, enter the vertical case\n", pt1[0], pt2[0]); + + p1_distance = pt1[1]; + pt_distance = (pt2[1] - p1_distance); + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } else { + /* The slope need to compute here. In shader, the viewport set will change + the orginal slope and the slope which is vertical to it will not be correct.*/ + slope = - (float)(src_picture->pSourcePict->linear.p2.x - src_picture->pSourcePict->linear.p1.x) / + (float)(src_picture->pSourcePict->linear.p2.y - src_picture->pSourcePict->linear.p1.y); + slope = slope * yscale / xscale; + dispatch->glUniform1f(pt_slope_uniform_location, slope); + dispatch->glUniform1i(hor_ver_uniform_location, 0); + + cos_val = sqrt(1.0 / (slope * slope + 1.0)); + dispatch->glUniform1f(cos_val_uniform_location, cos_val); + + p1_distance = (pt1[1] - pt1[0] * slope) * cos_val; + pt_distance = (pt2[1] - pt2[0] * slope) * cos_val - p1_distance; + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } + + /* set the transform matrix. */ /* Now rendering. */ + glamor_emit_composite_rect(screen, tex_vertices, NULL, vertices); + + if (glamor_priv->render_nr_verts) { + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + else { + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } + + dispatch->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL); + } + + /* Do the clear logic.*/ + if (stops_count > LINEAR_DEFAULT_STOPS) { + free(n_stops); + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + + if (src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS) + dispatch->glDeleteProgram(gradient_prog); + + glamor_put_dispatch(glamor_priv); + return dst_picture; + +GRADIENT_FAIL: + if (dst_picture) { + FreePicture(dst_picture, 0); + } + + if (stops_count > LINEAR_DEFAULT_STOPS) { + if (n_stops) + free(n_stops); + if (stop_colors) + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + if (src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS) + dispatch->glDeleteProgram(gradient_prog); + glamor_put_dispatch(glamor_priv); + return NULL; +} +#undef LINEAR_DEFAULT_STOPS + static PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, - PicturePtr source, - int x_source, - int y_source, int width, int height) + PicturePtr source, + int x_source, + int y_source, int width, int height) { PixmapPtr pixmap; - PicturePtr dst; + PicturePtr dst = NULL; int error; PictFormatShort format; if (!source->pDrawable) @@ -1312,6 +2254,22 @@ glamor_convert_gradient_picture(ScreenPtr screen, else format = source->format; + if (!source->pDrawable) { + if (source->pSourcePict->type == SourcePictTypeLinear) { + dst = _glamor_generate_linear_gradient_picture(screen, + source, x_source, y_source, width, height, format); + } + + if (dst) { +#if 0 /* Debug to compare it to pixman, Enable it if needed. */ + glamor_compare_pictures(screen, source, + dst, x_source, y_source, width, height, + 0, 3); +#endif + return dst; + } + } + pixmap = glamor_create_pixmap(screen, width, height, @@ -1322,11 +2280,11 @@ glamor_convert_gradient_picture(ScreenPtr screen, return NULL; dst = CreatePicture(0, - &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), - format), - 0, 0, serverClient, &error); + &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, 0, serverClient, &error); glamor_destroy_pixmap(pixmap); if (!dst) return NULL; @@ -1334,7 +2292,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, ValidatePicture(dst); fbComposite(PictOpSrc, source, NULL, dst, x_source, y_source, - 0, 0, 0, 0, width, height); + 0, 0, 0, 0, width, height); return dst; } From 1f4486c10bb2201830af251eede8cc4dbb857953 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 23 Mar 2012 04:06:06 +0800 Subject: [PATCH 312/462] Add the feature for radial gradient using shader. Add the feature for radial gradient using shader. The transform matrix and the 4 type of repeat mode are supported. Less than 2/255 difference for every color component comparing to pixman's result. Extract the common logic of linear and radial's to another shader. Reviewed-by: Chris Wilson Reviewed-by: Zhigang Gong Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 907 +++++++++++++++++++++++++++++++---------- 1 file changed, 700 insertions(+), 207 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6304167ea..042fabe2d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1275,6 +1275,345 @@ done: return ret; } +static GLint +_glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_array) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + char *gradient_fs = NULL; + GLint gradient_prog = 0; + GLint fs_getcolor_prog; + + const char *gradient_fs_getcolor = + GLAMOR_DEFAULT_PRECISION + "uniform int n_stop;\n" + "uniform float stops[%d];\n" + "uniform vec4 stop_colors[%d];\n" + "vec4 get_color(float stop_len)\n" + "{\n" + " int i = 0;\n" + " float new_alpha; \n" + " vec4 gradient_color;\n" + " float percentage; \n" + " for(i = 0; i < n_stop - 1; i++) {\n" + " if(stop_len < stops[i])\n" + " break; \n" + " }\n" + " \n" + " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n" + " if(stops[i] - stops[i-1] > 2.0)\n" + " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. + " new_alpha = percentage * stop_colors[i].a + \n" + " (1.0-percentage) * stop_colors[i-1].a; \n" + " gradient_color = vec4((percentage * stop_colors[i].rgb \n" + " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" + " return gradient_color;\n" + "}\n"; + + /* Because the array access for shader is very slow, the performance is very low + if use array. So use global uniform to replace for it if the number of n_stops is small.*/ + const char *gradient_fs_getcolor_no_array = + GLAMOR_DEFAULT_PRECISION + "uniform int n_stop;\n" + "uniform float stop0;\n" + "uniform float stop1;\n" + "uniform float stop2;\n" + "uniform float stop3;\n" + "uniform float stop4;\n" + "uniform float stop5;\n" + "uniform float stop6;\n" + "uniform float stop7;\n" + "uniform vec4 stop_color0;\n" + "uniform vec4 stop_color1;\n" + "uniform vec4 stop_color2;\n" + "uniform vec4 stop_color3;\n" + "uniform vec4 stop_color4;\n" + "uniform vec4 stop_color5;\n" + "uniform vec4 stop_color6;\n" + "uniform vec4 stop_color7;\n" + "\n" + "vec4 get_color(float stop_len)\n" + "{\n" + " float stop_after;\n" + " float stop_before;\n" + " vec4 stop_color_before;\n" + " vec4 stop_color_after;\n" + " float new_alpha; \n" + " vec4 gradient_color;\n" + " float percentage; \n" + " \n" + " if((stop_len < stop0) && (n_stop >= 1)) {\n" + " stop_color_before = stop_color0;\n" + " stop_color_after = stop_color0;\n" + " stop_after = stop0;\n" + " stop_before = stop0;\n" + " percentage = 0.0;\n" + " } else if((stop_len < stop1) && (n_stop >= 2)) {\n" + " stop_color_before = stop_color0;\n" + " stop_color_after = stop_color1;\n" + " stop_after = stop1;\n" + " stop_before = stop0;\n" + " percentage = (stop_len - stop0)/(stop1 - stop0);\n" + " } else if((stop_len < stop2) && (n_stop >= 3)) {\n" + " stop_color_before = stop_color1;\n" + " stop_color_after = stop_color2;\n" + " stop_after = stop2;\n" + " stop_before = stop1;\n" + " percentage = (stop_len - stop1)/(stop2 - stop1);\n" + " } else if((stop_len < stop3) && (n_stop >= 4)){\n" + " stop_color_before = stop_color2;\n" + " stop_color_after = stop_color3;\n" + " stop_after = stop3;\n" + " stop_before = stop2;\n" + " percentage = (stop_len - stop2)/(stop3 - stop2);\n" + " } else if((stop_len < stop4) && (n_stop >= 5)){\n" + " stop_color_before = stop_color3;\n" + " stop_color_after = stop_color4;\n" + " stop_after = stop4;\n" + " stop_before = stop3;\n" + " percentage = (stop_len - stop3)/(stop4 - stop3);\n" + " } else if((stop_len < stop5) && (n_stop >= 6)){\n" + " stop_color_before = stop_color4;\n" + " stop_color_after = stop_color5;\n" + " stop_after = stop5;\n" + " stop_before = stop4;\n" + " percentage = (stop_len - stop4)/(stop5 - stop4);\n" + " } else if((stop_len < stop6) && (n_stop >= 7)){\n" + " stop_color_before = stop_color5;\n" + " stop_color_after = stop_color6;\n" + " stop_after = stop6;\n" + " stop_before = stop5;\n" + " percentage = (stop_len - stop5)/(stop6 - stop5);\n" + " } else if((stop_len < stop7) && (n_stop >= 8)){\n" + " stop_color_before = stop_color6;\n" + " stop_color_after = stop_color7;\n" + " stop_after = stop7;\n" + " stop_before = stop6;\n" + " percentage = (stop_len - stop6)/(stop7 - stop6);\n" + " } else {\n" + " stop_color_before = stop_color7;\n" + " stop_color_after = stop_color7;\n" + " stop_after = stop7;\n" + " stop_before = stop7;\n" + " percentage = 0.0;\n" + " }\n" + " if(stop_after - stop_before > 2.0)\n" + " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. + " new_alpha = percentage * stop_color_after.a + \n" + " (1.0-percentage) * stop_color_before.a; \n" + " gradient_color = vec4((percentage * stop_color_after.rgb \n" + " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" + " return gradient_color;\n" + "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + if(use_array) { + XNFasprintf(&gradient_fs, + gradient_fs_getcolor, stops_count, stops_count); + fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + gradient_fs); + free(gradient_fs); + } else { + fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + gradient_fs_getcolor_no_array); + } + + return fs_getcolor_prog; +} + +static GLint +_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int use_array) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + GLint gradient_prog = 0; + char *gradient_fs = NULL; + GLint fs_main_prog, fs_getcolor_prog, vs_prog; + + const char *gradient_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" + "}\n"; + + /* + * Refer to pixman radial gradient. + * + * The problem is given the two circles of c1 and c2 with the radius of r1 and + * r1, we need to caculate the t, which is used to do interpolate with stops, + * using the fomula: + * length((1-t)*c1 + t*c2 - p) = (1-t)*r1 + t*r2 + * expand the fomula with xy coond, get the following: + * sqrt(sqr((1-t)*c1.x + t*c2.x - p.x) + sqr((1-t)*c1.y + t*c2.y - p.y)) + * = (1-t)r1 + t*r2 + * <====> At*t- 2Bt + C = 0 + * where A = sqr(c2.x - c1.x) + sqr(c2.y - c1.y) - sqr(r2 -r1) + * B = (p.x - c1.x)*(c2.x - c1.x) + (p.y - c1.y)*(c2.y - c1.y) + r1*(r2 -r1) + * C = sqr(p.x - c1.x) + sqr(p.y - c1.y) - r1*r1 + * + * solve the fomula and we get the result of + * t = (B + sqrt(B*B - A*C)) / A or + * t = (B - sqrt(B*B - A*C)) / A (quadratic equation have two solutions) + * + * The solution we are going to prefer is the bigger one, unless the + * radius associated to it is negative (or it falls outside the valid t range) + */ + + const char *gradient_fs_template = + GLAMOR_DEFAULT_PRECISION + "uniform mat3 transform_mat;\n" + "uniform int repeat_type;\n" + "uniform float A_value;\n" + "uniform vec2 c1;\n" + "uniform float r1;\n" + "uniform vec2 c2;\n" + "uniform float r2;\n" + "varying vec2 source_texture;\n" + "\n" + "vec4 get_color(float stop_len);\n" + "\n" + "int t_invalid;\n" + "\n" + "float get_stop_len()\n" + "{\n" + " float t = 0.0;\n" + " float sqrt_value;\n" + " int revserse = 0;\n" + " t_invalid = 0;\n" + " \n" + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" + " vec3 source_texture_trans = transform_mat * tmp;\n" + " source_texture_trans.xy = source_texture_trans.xy/source_texture_trans.z;\n" + " float B_value = (source_texture_trans.x - c1.x) * (c2.x - c1.x)\n" + " + (source_texture_trans.y - c1.y) * (c2.y - c1.y)\n" + " + r1 * (r2 - r1);\n" + " float C_value = (source_texture_trans.x - c1.x) * (source_texture_trans.x - c1.x)\n" + " + (source_texture_trans.y - c1.y) * (source_texture_trans.y - c1.y)\n" + " - r1*r1;\n" + " if(abs(A_value) < 0.00001) {\n" + " if(B_value == 0.0) {\n" + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " t = 0.5 * C_value / B_value;" + " } else {\n" + " sqrt_value = B_value * B_value - A_value * C_value;\n" + " if(sqrt_value < 0.0) {\n" + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " sqrt_value = sqrt(sqrt_value);\n" + " t = (B_value + sqrt_value) / A_value;\n" + " }\n" + " if(repeat_type == %d) {\n" // RepeatNone case. + " if((t <= 0.0) || (t > 1.0))\n" + // try another if first one invalid + " t = (B_value - sqrt_value) / A_value;\n" + " \n" + " if((t <= 0.0) || (t > 1.0)) {\n" //still invalid, return. + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " } else {\n" + " if(t * (r2 - r1) <= -1.0 * r1)\n" + // try another if first one invalid + " t = (B_value - sqrt_value) / A_value;\n" + " \n" + " if(t * (r2 -r1) <= -1.0 * r1) {\n" //still invalid, return. + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " }\n" + " \n" + " if(repeat_type == %d){\n" // repeat normal + " while(t > 1.0) \n" + " t = t - 1.0; \n" + " while(t < 0.0) \n" + " t = t + 1.0; \n" + " }\n" + " \n" + " if(repeat_type == %d) {\n" // repeat reflect + " while(t > 1.0) {\n" + " t = t - 1.0; \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " while(t < 0.0) {\n" + " t = t + 1.0; \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " if(revserse == 1) {\n" + " t = 1.0 - t; \n" + " }\n" + " }\n" + " \n" + " return t;\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " float stop_len = get_stop_len();\n" + " if(t_invalid == 1) {\n" + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" + " } else {\n" + " gl_FragColor = get_color(stop_len);\n" + " }\n" + "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + gradient_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, + GL_VERTEX_SHADER, gradient_vs); + + XNFasprintf(&gradient_fs, + gradient_fs_template, + PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + + fs_main_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); + + free(gradient_fs); + + fs_getcolor_prog = _glamor_create_getcolor_fs_program(screen, + stops_count, use_array); + + dispatch->glAttachShader(gradient_prog, vs_prog); + dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); + dispatch->glAttachShader(gradient_prog, fs_main_prog); + + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_positionsition"); + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); + + glamor_link_glsl_prog(dispatch, gradient_prog); + + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); + return gradient_prog; +} + static GLint _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int use_array) { @@ -1283,7 +1622,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us GLint gradient_prog = 0; char *gradient_fs = NULL; - GLint fs_prog, vs_prog; + GLint fs_main_prog, fs_getcolor_prog, vs_prog; const char *gradient_vs = GLAMOR_DEFAULT_PRECISION @@ -1350,9 +1689,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us "uniform mat3 transform_mat;\n" "uniform int repeat_type;\n" "uniform int hor_ver;\n" - "uniform int n_stop;\n" - "uniform float stops[%d];\n" - "uniform vec4 stop_colors[%d];\n" "uniform vec4 pt1;\n" "uniform vec4 pt2;\n" "uniform float pt_slope;\n" @@ -1361,122 +1697,9 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us "uniform float pt_distance;\n" "varying vec2 source_texture;\n" "\n" - "vec4 get_color()\n" - "{\n" - " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" - " float len_percentage;\n" - " float distance;\n" - " float _p1_distance;\n" - " float _pt_distance;\n" - " float y_dist;\n" - " float new_alpha; \n" - " int i = n_stop - 1;\n" - " int revserse = 0;\n" - " vec4 gradient_color;\n" - " float percentage; \n" - " vec3 source_texture_trans = transform_mat * tmp;\n" - " \n" - " if(hor_ver == 0) { \n" //Normal case. - " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n" - " distance = y_dist * cos_val;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " \n" - " } else if (hor_ver == 1) {\n"//horizontal case. - " distance = source_texture_trans.x;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " } else if (hor_ver == 2) {\n"//vertical case. - " distance = source_texture_trans.y;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " } \n" - " \n" - " distance = distance - _p1_distance; \n" - " \n" - " if(repeat_type == %d){\n" // repeat normal - " while(distance > _pt_distance) \n" - " distance = distance - (_pt_distance); \n" - " while(distance < 0.0) \n" - " distance = distance + (_pt_distance); \n" - " }\n" - " \n" - " if(repeat_type == %d) {\n" // repeat reflect - " while(distance > _pt_distance) {\n" - " distance = distance - (_pt_distance); \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " while(distance < 0.0) {\n" - " distance = distance + (_pt_distance); \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " if(revserse == 1) {\n" - " distance = (_pt_distance) - distance; \n" - " }\n" - " }\n" - " \n" - " len_percentage = distance/(_pt_distance);\n" - " for(i = 0; i < n_stop - 1; i++) {\n" - " if(len_percentage < stops[i])\n" - " break; \n" - " }\n" - " \n" - " percentage = (len_percentage - stops[i-1])/(stops[i] - stops[i-1]);\n" - " if(stops[i] - stops[i-1] > 2.0)\n" - " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. - " new_alpha = percentage * stop_colors[i].a + \n" - " (1.0-percentage) * stop_colors[i-1].a; \n" - " gradient_color = vec4((percentage * stop_colors[i].rgb \n" - " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n" - " new_alpha);\n" - " \n" - " return gradient_color;\n" - "}\n" + "vec4 get_color(float stop_len);\n" "\n" - "void main()\n" - "{\n" - " gl_FragColor = get_color();\n" - "}\n"; - - /* Because the array access for shader is very slow, the performance is very low - if use array. So use global uniform to replace for it if the number of n_stops is small.*/ - const char *gradient_fs_no_array_template = - GLAMOR_DEFAULT_PRECISION - "uniform mat3 transform_mat;\n" - "uniform int repeat_type;\n" - "uniform int hor_ver;\n" - "uniform int n_stop;\n" - "uniform float stop0;\n" - "uniform float stop1;\n" - "uniform float stop2;\n" - "uniform float stop3;\n" - "uniform float stop4;\n" - "uniform float stop5;\n" - "uniform float stop6;\n" - "uniform float stop7;\n" - "uniform vec4 stop_color0;\n" - "uniform vec4 stop_color1;\n" - "uniform vec4 stop_color2;\n" - "uniform vec4 stop_color3;\n" - "uniform vec4 stop_color4;\n" - "uniform vec4 stop_color5;\n" - "uniform vec4 stop_color6;\n" - "uniform vec4 stop_color7;\n" - "uniform vec4 pt1;\n" - "uniform vec4 pt2;\n" - "uniform float pt_slope;\n" - "uniform float cos_val;\n" - "uniform float p1_distance;\n" - "uniform float pt_distance;\n" - "varying vec2 source_texture;\n" - "\n" - "vec4 get_color()\n" + "float get_stop_len()\n" "{\n" " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" " float len_percentage;\n" @@ -1532,7 +1755,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us " if(revserse == 0)\n" " revserse = 1;\n" " else\n" - " revserse = 0;\n" + " revserse = 0;\n" " }\n" " if(revserse == 1) {\n" " distance = (_pt_distance) - distance; \n" @@ -1540,75 +1763,14 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us " }\n" " \n" " len_percentage = distance/(_pt_distance);\n" - " if((len_percentage < stop0) && (n_stop >= 1)) {\n" - " stop_color_before = stop_color0;\n" - " stop_color_after = stop_color0;\n" - " stop_after = stop0;\n" - " stop_before = stop0;\n" - " percentage = 0.0;\n" - " } else if((len_percentage < stop1) && (n_stop >= 2)) {\n" - " stop_color_before = stop_color0;\n" - " stop_color_after = stop_color1;\n" - " stop_after = stop1;\n" - " stop_before = stop0;\n" - " percentage = (len_percentage - stop0)/(stop1 - stop0);\n" - " } else if((len_percentage < stop2) && (n_stop >= 3)) {\n" - " stop_color_before = stop_color1;\n" - " stop_color_after = stop_color2;\n" - " stop_after = stop2;\n" - " stop_before = stop1;\n" - " percentage = (len_percentage - stop1)/(stop2 - stop1);\n" - " } else if((len_percentage < stop3) && (n_stop >= 4)){\n" - " stop_color_before = stop_color2;\n" - " stop_color_after = stop_color3;\n" - " stop_after = stop3;\n" - " stop_before = stop2;\n" - " percentage = (len_percentage - stop2)/(stop3 - stop2);\n" - " } else if((len_percentage < stop4) && (n_stop >= 5)){\n" - " stop_color_before = stop_color3;\n" - " stop_color_after = stop_color4;\n" - " stop_after = stop4;\n" - " stop_before = stop3;\n" - " percentage = (len_percentage - stop3)/(stop4 - stop3);\n" - " } else if((len_percentage < stop5) && (n_stop >= 6)){\n" - " stop_color_before = stop_color4;\n" - " stop_color_after = stop_color5;\n" - " stop_after = stop5;\n" - " stop_before = stop4;\n" - " percentage = (len_percentage - stop4)/(stop5 - stop4);\n" - " } else if((len_percentage < stop6) && (n_stop >= 7)){\n" - " stop_color_before = stop_color5;\n" - " stop_color_after = stop_color6;\n" - " stop_after = stop6;\n" - " stop_before = stop5;\n" - " percentage = (len_percentage - stop5)/(stop6 - stop5);\n" - " } else if((len_percentage < stop7) && (n_stop >= 8)){\n" - " stop_color_before = stop_color6;\n" - " stop_color_after = stop_color7;\n" - " stop_after = stop7;\n" - " stop_before = stop6;\n" - " percentage = (len_percentage - stop6)/(stop7 - stop6);\n" - " } else {\n" - " stop_color_before = stop_color7;\n" - " stop_color_after = stop_color7;\n" - " stop_after = stop7;\n" - " stop_before = stop7;\n" - " percentage = 0.0;\n" - " }\n" - " if(stop_after - stop_before > 2.0)\n" - " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. - " new_alpha = percentage * stop_color_after.a + \n" - " (1.0-percentage) * stop_color_before.a; \n" - " gradient_color = vec4((percentage * stop_color_after.rgb \n" - " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" - " new_alpha);\n" " \n" - " return gradient_color;\n" + " return len_percentage;\n" "}\n" "\n" "void main()\n" "{\n" - " gl_FragColor = get_color();\n" + " float stop_len = get_stop_len();\n" + " gl_FragColor = get_color(stop_len);\n" "}\n"; glamor_priv = glamor_get_screen_private(screen); @@ -1617,23 +1779,22 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us gradient_prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(dispatch, - GL_VERTEX_SHADER, gradient_vs); + GL_VERTEX_SHADER, gradient_vs); - if (use_array) { - XNFasprintf(&gradient_fs, - gradient_fs_template, stops_count, stops_count, - PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); - } else { - XNFasprintf(&gradient_fs, - gradient_fs_no_array_template, - PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); - } - fs_prog = glamor_compile_glsl_prog(dispatch, - GL_FRAGMENT_SHADER, gradient_fs); + XNFasprintf(&gradient_fs, + gradient_fs_template, + PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + + fs_main_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); free(gradient_fs); + fs_getcolor_prog = _glamor_create_getcolor_fs_program(screen, + stops_count, use_array); + dispatch->glAttachShader(gradient_prog, vs_prog); - dispatch->glAttachShader(gradient_prog, fs_prog); + dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); + dispatch->glAttachShader(gradient_prog, fs_main_prog); dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position"); dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); @@ -1647,6 +1808,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us } #define LINEAR_DEFAULT_STOPS 6 + 2 +#define RADIAL_DEFAULT_STOPS 6 + 2 void glamor_init_gradient_shader(ScreenPtr screen) @@ -1658,6 +1820,9 @@ glamor_init_gradient_shader(ScreenPtr screen) glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR] = _glamor_create_linear_gradient_program(screen, LINEAR_DEFAULT_STOPS, 0); + glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL] = + _glamor_create_radial_gradient_program(screen, + RADIAL_DEFAULT_STOPS, 0); } void @@ -1671,13 +1836,15 @@ glamor_fini_gradient_shader(ScreenPtr screen) dispatch->glDeleteProgram( glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR]); + dispatch->glDeleteProgram( + glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL]); glamor_put_dispatch(glamor_priv); } static void _glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], - int width, int height) + int width, int height, int normalize) { /* * Because in the shader program, we normalize all the pixel cood to [0, 1], @@ -1713,20 +1880,20 @@ _glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], to[0][0] = (float)pixman_fixed_to_double(from->matrix[0][0]); to[0][1] = (float)pixman_fixed_to_double(from->matrix[0][1]) - * ((float)height) / ((float)width); + * (normalize ? (((float)height) / ((float)width)) : 1.0); to[0][2] = (float)pixman_fixed_to_double(from->matrix[0][2]) - / ((float)width); + / (normalize ? ((float)width) : 1.0); to[1][0] = (float)pixman_fixed_to_double(from->matrix[1][0]) - * ((float)width) / ((float)height); + * (normalize ? (((float)width) / ((float)height)) : 1.0); to[1][1] = (float)pixman_fixed_to_double(from->matrix[1][1]); to[1][2] = (float)pixman_fixed_to_double(from->matrix[1][2]) - / ((float)height); + / (normalize ? ((float)height) : 1.0); to[2][0] = (float)pixman_fixed_to_double(from->matrix[2][0]) - * ((float)width); + * (normalize ? ((float)width) : 1.0); to[2][1] = (float)pixman_fixed_to_double(from->matrix[2][1]) - * ((float)height); + * (normalize ? ((float)height) : 1.0); to[2][2] = (float)pixman_fixed_to_double(from->matrix[2][2]); DEBUGF("the transform matrix is:\n%f\t%f\t%f\n%f\t%f\t%f\n%f\t%f\t%f\n", @@ -1877,6 +2044,329 @@ _glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, return count; } +static PicturePtr +_glamor_generate_radial_gradient_picture(ScreenPtr screen, + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + PicturePtr dst_picture = NULL; + PixmapPtr pixmap = NULL; + glamor_pixmap_private *pixmap_priv; + GLint gradient_prog = 0; + int error; + float tex_vertices[8]; + int stops_count; + int count = 0; + GLfloat *stop_colors = NULL; + GLfloat *n_stops = NULL; + GLfloat xscale, yscale; + float vertices[8]; + float transform_mat[3][3]; + static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}}; + GLfloat stop_colors_st[RADIAL_DEFAULT_STOPS*4]; + GLfloat n_stops_st[RADIAL_DEFAULT_STOPS]; + GLfloat A_value; + GLfloat cxy[4]; + float c1x, c1y, c2x, c2y, r1, r2; + + GLint transform_mat_uniform_location; + GLint repeat_type_uniform_location; + GLint n_stop_uniform_location; + GLint stops_uniform_location; + GLint stop_colors_uniform_location; + GLint stop0_uniform_location; + GLint stop1_uniform_location; + GLint stop2_uniform_location; + GLint stop3_uniform_location; + GLint stop4_uniform_location; + GLint stop5_uniform_location; + GLint stop6_uniform_location; + GLint stop7_uniform_location; + GLint stop_color0_uniform_location; + GLint stop_color1_uniform_location; + GLint stop_color2_uniform_location; + GLint stop_color3_uniform_location; + GLint stop_color4_uniform_location; + GLint stop_color5_uniform_location; + GLint stop_color6_uniform_location; + GLint stop_color7_uniform_location; + GLint A_value_uniform_location; + GLint c1_uniform_location; + GLint r1_uniform_location; + GLint c2_uniform_location; + GLint r2_uniform_location; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + /* Create a pixmap with VBO. */ + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), + GLAMOR_CREATE_PIXMAP_FIXUP); + if (!pixmap) + goto GRADIENT_FAIL; + + dst_picture = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), format), + 0, 0, serverClient, &error); + + /* Release the reference, picture will hold the last one. */ + glamor_destroy_pixmap(pixmap); + + if (!dst_picture) + goto GRADIENT_FAIL; + + ValidatePicture(dst_picture); + + stops_count = src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS ? + src_picture->pSourcePict->radial.nstops + 2 : RADIAL_DEFAULT_STOPS; + + /* Because the max value of nstops is unkown, so create a programwhen nstops > default.*/ + if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_DEFAULT_STOPS) { + gradient_prog = glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL]; + } else { + gradient_prog = _glamor_create_radial_gradient_program(screen, + src_picture->pSourcePict->radial.nstops + 2, 1); + } + + /* Bind all the uniform vars .*/ + transform_mat_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + n_stop_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "n_stop"); + A_value_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "A_value"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + c1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "c1"); + r1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "r1"); + c2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "c2"); + r2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "r2"); + + if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_DEFAULT_STOPS) { + stop0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop0"); + stop1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop1"); + stop2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop2"); + stop3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop3"); + stop4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop4"); + stop5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop5"); + stop6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop6"); + stop7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop7"); + + stop_color0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); + stop_color1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); + stop_color2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); + stop_color3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); + stop_color4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); + stop_color5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); + stop_color6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); + stop_color7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); + } else { + stops_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stops"); + stop_colors_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); + } + + dispatch->glUseProgram(gradient_prog); + + dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); + + + if (src_picture->transform) { + _glamor_gradient_convert_trans_matrix(src_picture->transform, + transform_mat, + width, height, 0); + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &transform_mat[0][0]); + } else { + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &identity_mat[0][0]); + } + + if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, + &xscale, &yscale, x_source, y_source, + vertices, tex_vertices, 0)) + goto GRADIENT_FAIL; + + /* Set all the stops and colors to shader. */ + if (stops_count > RADIAL_DEFAULT_STOPS) { + stop_colors = malloc(4 * stops_count * sizeof(float)); + if (stop_colors == NULL) { + ErrorF("Failed to allocate stop_colors memory.\n"); + goto GRADIENT_FAIL; + } + + n_stops = malloc(stops_count * sizeof(float)); + if (n_stops == NULL) { + ErrorF("Failed to allocate n_stops memory.\n"); + goto GRADIENT_FAIL; + } + } else { + stop_colors = stop_colors_st; + n_stops = n_stops_st; + } + + count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, + stop_colors, n_stops); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + int j = 0; + dispatch->glUniform4f(stop_color0_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color1_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color2_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color3_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color4_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color5_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color6_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color7_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + + j = 0; + dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); + dispatch->glUniform1i(n_stop_uniform_location, count); + } else { + dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); + dispatch->glUniform1fv(stops_uniform_location, count, n_stops); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + + c1x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.x); + c1y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.y); + c2x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.x); + c2y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.y); + + r1 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.radius); + r2 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.radius); + + + cxy[0] = c1x; + cxy[1] = c1y; + dispatch->glUniform2fv(c1_uniform_location, 1, cxy); + dispatch->glUniform1f(r1_uniform_location, r1); + + cxy[0] = c2x; + cxy[1] = c2y; + dispatch->glUniform2fv(c2_uniform_location, 1, cxy); + dispatch->glUniform1f(r2_uniform_location, r2); + + A_value = (c2x - c1x) * (c2x - c1x) + (c2y - c1y) * (c2y - c1y) - (r2 - r1) * (r2 - r1); + dispatch->glUniform1f(A_value_uniform_location, A_value); + + DEBUGF("C1:(%f, %f) R1:%f\nC2:(%f, %f) R2:%f\nA = %f\n", + c1x, c1y, r1, c2x, c2y, r2, A_value); + + glamor_emit_composite_rect(screen, tex_vertices, NULL, vertices); + + if (glamor_priv->render_nr_verts) { + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + else { + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } + + dispatch->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL); + } + + + /* Do the clear logic.*/ + if (stops_count > RADIAL_DEFAULT_STOPS) { + free(n_stops); + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + + if (src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS) + dispatch->glDeleteProgram(gradient_prog); + + glamor_put_dispatch(glamor_priv); + return dst_picture; + +GRADIENT_FAIL: + if (dst_picture) { + FreePicture(dst_picture, 0); + } + + if (stops_count > RADIAL_DEFAULT_STOPS) { + if (n_stops) + free(n_stops); + if (stop_colors) + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + if (src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS) + dispatch->glDeleteProgram(gradient_prog); + glamor_put_dispatch(glamor_priv); + return NULL; +} + static PicturePtr _glamor_generate_linear_gradient_picture(ScreenPtr screen, PicturePtr src_picture, @@ -1905,8 +2395,8 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, float vertices[8]; float transform_mat[3][3]; static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0}}; + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}}; GLfloat stop_colors_st[LINEAR_DEFAULT_STOPS*4]; GLfloat n_stops_st[LINEAR_DEFAULT_STOPS]; @@ -2046,7 +2536,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, if (src_picture->transform) { _glamor_gradient_convert_trans_matrix(src_picture->transform, transform_mat, - width, height); + width, height, 1); dispatch->glUniformMatrix3fv(transform_mat_uniform_location, 1, 1, &transform_mat[0][0]); } else { @@ -2258,6 +2748,9 @@ glamor_convert_gradient_picture(ScreenPtr screen, if (source->pSourcePict->type == SourcePictTypeLinear) { dst = _glamor_generate_linear_gradient_picture(screen, source, x_source, y_source, width, height, format); + } else if (source->pSourcePict->type == SourcePictTypeRadial) { + dst = _glamor_generate_radial_gradient_picture(screen, + source, x_source, y_source, width, height, format); } if (dst) { From 94186db527b33b2623eb26a7f1ae0c4c0fca66a4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 26 Mar 2012 19:03:20 +0800 Subject: [PATCH 313/462] glamor_fill: Should restore alu to GXcopy. Signed-off-by: Zhigang Gong --- glamor/glamor_fill.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 85733099b..e8419c633 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -206,6 +206,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); + glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); return TRUE; } From 7036cfdd0d29f4e13d432893a4f386cd3d632de7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 16 Mar 2012 16:42:46 +0800 Subject: [PATCH 314/462] glamor_fbo: Added one macro to disable fbo cache. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 3ae656250..d212bd4a2 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -8,6 +8,8 @@ #define GLAMOR_CACHE_EXACT_SIZE 1 #define GLAMOR_CACHE_TEXTURE 2 +//#define NO_FBO_CACHE 1 + /* Loop from the tail to the head. */ #define xorg_list_for_each_entry_reverse(pos, head, member) \ for (pos = __container_of((head)->prev, pos, member); \ @@ -80,7 +82,9 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry; int size; - +#ifdef NO_FBO_CACHE + return NULL; +#else if (!(flag & GLAMOR_CACHE_TEXTURE)) cache = &glamor_priv->fbo_cache[cache_format(format)] [cache_wbucket(w)] @@ -117,6 +121,7 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, } return NULL; +#endif } void @@ -135,11 +140,14 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo) } -void +static void glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) { struct xorg_list *cache; - +#ifdef NO_FBO_CACHE + glamor_purge_fbo(fbo); + return; +#else if (fbo->fb == 0) { glamor_purge_fbo(fbo); return; @@ -157,6 +165,7 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); xorg_list_add(&fbo->list, cache); fbo->expire = fbo->glamor_priv->tick + GLAMOR_CACHE_EXPIRE_MAX; +#endif } glamor_pixmap_fbo * From 57e29ebdc13d0ef145e4c70c1406af3229a92ad8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 6 Apr 2012 11:14:21 +0800 Subject: [PATCH 315/462] glamor_render: Disable gradient shader conversion due to bug. I found when enable the gradient shader, the firefox's tab's background has incorrect rendering result. Need furthr investigation, for now, just disable it. Signed-off-by: Zhigang Gong --- glamor/glamor_priv.h | 1 + glamor/glamor_render.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index ad6873757..54bbdb1ab 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -714,6 +714,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD //#define GLAMOR_DELAYED_FILLING +//#define GLAMOR_GRADIENT_SHADER diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 042fabe2d..00a6e1ec9 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -2743,7 +2743,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, format = PICT_a8r8g8b8; else format = source->format; - +#ifdef GLAMOR_GRADIENT_SHADER if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeLinear) { dst = _glamor_generate_linear_gradient_picture(screen, @@ -2762,7 +2762,7 @@ glamor_convert_gradient_picture(ScreenPtr screen, return dst; } } - +#endif pixmap = glamor_create_pixmap(screen, width, height, From 55fdc7b196904a4e537f429d06d36081a0c9a60d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 5 Apr 2012 20:27:35 +0800 Subject: [PATCH 316/462] glamor_utils: Added debug function to dump depth 15/16 pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_utils.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 75ebc7ed9..29b7b12b8 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -658,6 +658,24 @@ static inline void _glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int } } +static inline void _glamor_dump_pixmap_sword(PixmapPtr pixmap, int x, int y, int w, int h) +{ + int i,j; + unsigned short * p = pixmap->devPrivate.ptr; + int stride = pixmap->devKind / 2; + + p = p + y * stride + x; + + for (i = 0; i < h; i++) + { + ErrorF("line %3d: ", i); + for(j = 0; j < w; j++) + ErrorF("%2x ", p[j]); + p += stride; + ErrorF("\n"); + } +} + static inline void _glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int w, int h) { int i,j; @@ -678,17 +696,25 @@ static inline void _glamor_dump_pixmap_word(PixmapPtr pixmap, int x, int y, int static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h) { + w = ((x + w) > pixmap->drawable.width) ? (pixmap->drawable.width - x) : w; + h = ((y + h) > pixmap->drawable.height) ? (pixmap->drawable.height - y) : h; + glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO); switch (pixmap->drawable.depth) { case 8: _glamor_dump_pixmap_byte(pixmap, x, y, w, h); break; + case 15: + case 16: + _glamor_dump_pixmap_sword(pixmap, x, y, w, h); + break; + case 24: case 32: _glamor_dump_pixmap_word(pixmap, x, y, w, h); break; default: - assert(0); + ErrorF("dump depth %d, not implemented.\n", pixmap->drawable.depth); } glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); } From 3add3750658107bd18592a8672caa8bed0c8931c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 5 Apr 2012 21:53:44 +0800 Subject: [PATCH 317/462] gles2: Fixed color conversion for the formats except 1555 and 2101010. This patch fixed two major problems when we do the color convesion with GLES2. 1. lack of necessary formats in FBO pool. GLES2 has three different possible texture formats, GL_RGBA, GL_BGRA and GL_ALPHA. Previous implementation only has one bucket for all the three formats which may reuse a incorrect texture format when do the cache lookup. After this fix, we can enable fbo safely when running with GLES2. 2. Refine the format matching method in glamor_get_tex_format_type_from_pictformat. If both revertion and swap_rb are needed, for example use GL_RGBA to represent PICT_b8g8r8a8. Then the downloading and uploading should be handled differently. The picture's format is PICT_b8g8r8a8, Then the expecting color layout is as below (little endian): 0 1 2 3 : address a r g b Now the in GLES2 the supported color format is GL_RGBA, type is GL_UNSIGNED_TYPE, then we need to shuffle the fragment color as : frag_color = sample(texture).argb; before we use glReadPixel to get it back. For the uploading process, the shuffle is a revert shuffle. We still use GL_RGBA, GL_UNSIGNED_BYTE to upload the color to a texture, then let's see 0 1 2 3 : address a r g b : correct colors R G B A : GL_RGBA with GL_UNSIGNED_BYTE Now we need to shuffle again, the mapping rule is r = G, g = B, b = A, a = R. Then the uploading shuffle is as below: frag_color = sample(texture).gbar; After this commit, gles2 version can pass render check with all the formats except those 1555/2101010. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 12 ++- glamor/glamor_copyarea.c | 10 +-- glamor/glamor_core.c | 115 ++++++++++++++++++------- glamor/glamor_fbo.c | 56 ++++++------ glamor/glamor_getimage.c | 29 ++++--- glamor/glamor_getspans.c | 31 ++++--- glamor/glamor_pixmap.c | 181 +++++++++++++++++++++------------------ glamor/glamor_priv.h | 19 ++-- glamor/glamor_putimage.c | 13 +-- glamor/glamor_setspans.c | 7 +- glamor/glamor_utils.h | 115 ++++++++++++++++++------- 11 files changed, 365 insertions(+), 223 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 532b9efae..8fc3b0534 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -84,6 +84,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; glamor_pixmap_fbo *fbo; + GLenum format; glamor_priv = glamor_get_screen_private(screen); pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -93,9 +94,10 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_destroy_fbo(fbo); } + gl_iformat_for_depth(pixmap->drawable.depth, &format); fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth, tex, 0); + format, tex, 0); if (fbo == NULL) { ErrorF("XXX fail to create fbo.\n"); @@ -133,11 +135,14 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_pixmap_fbo *fbo; int pitch; int flag; + GLenum format; if (w > 32767 || h > 32767) return NullPixmap; - if (usage == GLAMOR_CREATE_PIXMAP_CPU || (w == 0 && h == 0)) + if (usage == GLAMOR_CREATE_PIXMAP_CPU + || (w == 0 && h == 0) + || !glamor_check_pixmap_fbo_depth(depth)) return fbCreatePixmap(screen, w, h, depth, usage); else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); @@ -154,7 +159,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->glamor_priv = glamor_priv; pixmap_priv->type = type; - fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage); + gl_iformat_for_depth(depth, &format); + fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); if (fbo == NULL) { fbDestroyPixmap(pixmap); diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 87b53a983..b4880378c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -239,12 +239,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src, texcoords); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); - dispatch-> - glUniform1i(glamor_priv->finish_access_no_revert[0], - 1); - dispatch-> - glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); - + dispatch->glUniform1i(glamor_priv->finish_access_revert[0], + REVERT_NONE); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], + SWAP_NONE_UPLOADING); } else { GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, src_pixmap_priv); diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 0376388ca..f9c1db22f 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -107,6 +107,35 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access) return glamor_download_pixmap_to_cpu(pixmap, access); } +/* + * When downloading a unsupported color format to CPU memory, + we need to shuffle the color elements and then use a supported + color format to read it back to CPU memory. + + For an example, the picture's format is PICT_b8g8r8a8, + Then the expecting color layout is as below (little endian): + 0 1 2 3 : address + a r g b + + Now the in GLES2 the supported color format is GL_RGBA, type is + GL_UNSIGNED_TYPE, then we need to shuffle the fragment + color as : + frag_color = sample(texture).argb; + before we use glReadPixel to get it back. + + For the uploading process, the shuffle is a revert shuffle. + We still use GL_RGBA, GL_UNSIGNED_BYTE to upload the color + to a texture, then let's see + 0 1 2 3 : address + a r g b : correct colors + R G B A : GL_RGBA with GL_UNSIGNED_BYTE + + Now we need to shuffle again, the mapping rule is + r = G, g = B, b = A, a = R. Then the uploading shuffle is as + below: + frag_color = sample(texture).gbar; +*/ + void glamor_init_finish_access_shaders(ScreenPtr screen) { @@ -121,53 +150,67 @@ glamor_init_finish_access_shaders(ScreenPtr screen) " gl_Position = v_position;\n" " source_texture = v_texcoord0.xy;\n" "}\n"; - const char *fs_source = + const char *common_source = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D sampler;\n" - "uniform int no_revert;\n" + "uniform int revert;\n" "uniform int swap_rb;\n" + + "#define REVERT_NONE 0\n" + "#define REVERT_NORMAL 1\n" + "#define SWAP_NONE_DOWNLOADING 0\n" + "#define SWAP_DOWNLOADING 1\n" + "#define SWAP_UPLOADING 2\n" + "#define SWAP_NONE_UPLOADING 3\n"; + + const char *fs_source = "void main()\n" "{\n" - " if (no_revert == 1) \n" + " if (revert == REVERT_NONE) \n" " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = texture2D(sampler, source_texture).bgra;\n" + " if ((swap_rb != SWAP_NONE_DOWNLOADING) && (swap_rb != SWAP_NONE_UPLOADING)) \n" + " gl_FragColor = texture2D(sampler, source_texture).bgra;\n" " else \n" - " gl_FragColor = texture2D(sampler, source_texture).rgba;\n" + " gl_FragColor = texture2D(sampler, source_texture).rgba;\n" " } \n" " else \n" " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = texture2D(sampler, source_texture).argb;\n" - " else \n" - " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" + " if (swap_rb == SWAP_DOWNLOADING) \n" + " gl_FragColor = texture2D(sampler, source_texture).argb;\n" + " else if (swap_rb == SWAP_NONE_DOWNLOADING)\n" + " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" + " else if (swap_rb == SWAP_UPLOADING)\n" + " gl_FragColor = texture2D(sampler, source_texture).gbar;\n" + " else if (swap_rb == SWAP_NONE_UPLOADING)\n" + " gl_FragColor = texture2D(sampler, source_texture).abgr;\n" " } \n" "}\n"; const char *set_alpha_source = - GLAMOR_DEFAULT_PRECISION - "varying vec2 source_texture;\n" - "uniform sampler2D sampler;\n" - "uniform int no_revert;\n" - "uniform int swap_rb;\n" "void main()\n" "{\n" - " if (no_revert == 1) \n" + " if (revert == REVERT_NONE) \n" " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" + " if ((swap_rb != SWAP_NONE_DOWNLOADING) && (swap_rb != SWAP_NONE_UPLOADING)) \n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" " else \n" - " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" " } \n" " else \n" " { \n" - " if (swap_rb == 1) \n" - " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" - " else \n" - " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" - " } \n" "}\n"; + " if (swap_rb == SWAP_DOWNLOADING) \n" + " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" + " else if (swap_rb == SWAP_NONE_DOWNLOADING)\n" + " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" + " else if (swap_rb == SWAP_UPLOADING)\n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).gba, 1);\n" + " else if (swap_rb == SWAP_NONE_UPLOADING)\n" + " gl_FragColor = vec4(texture2D(sampler, source_texture).abg, 1);\n" + " } \n" + "}\n"; GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; GLint sampler_uniform_location; + char *source; glamor_priv = glamor_get_screen_private(screen); dispatch = glamor_get_dispatch(glamor_priv); @@ -176,8 +219,12 @@ glamor_init_finish_access_shaders(ScreenPtr screen) vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); + + XNFasprintf(&source, "%s%s", common_source, fs_source); fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - fs_source); + source); + free(source); + dispatch->glAttachShader(glamor_priv->finish_access_prog[0], vs_prog); dispatch->glAttachShader(glamor_priv->finish_access_prog[0], @@ -185,8 +232,12 @@ glamor_init_finish_access_shaders(ScreenPtr screen) avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source); + + XNFasprintf(&source, "%s%s", common_source, set_alpha_source); set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - set_alpha_source); + source); + free(source); + dispatch->glAttachShader(glamor_priv->finish_access_prog[1], avs_prog); dispatch->glAttachShader(glamor_priv->finish_access_prog[1], @@ -208,10 +259,10 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[1]); - glamor_priv->finish_access_no_revert[0] = + glamor_priv->finish_access_revert[0] = dispatch-> glGetUniformLocation(glamor_priv->finish_access_prog[0], - "no_revert"); + "revert"); glamor_priv->finish_access_swap_rb[0] = dispatch-> @@ -223,14 +274,14 @@ glamor_init_finish_access_shaders(ScreenPtr screen) "sampler"); dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); dispatch->glUniform1i(sampler_uniform_location, 0); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0], 1); + dispatch->glUniform1i(glamor_priv->finish_access_revert[0], 0); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); dispatch->glUseProgram(0); - glamor_priv->finish_access_no_revert[1] = + glamor_priv->finish_access_revert[1] = dispatch-> glGetUniformLocation(glamor_priv->finish_access_prog[1], - "no_revert"); + "revert"); glamor_priv->finish_access_swap_rb[1] = dispatch-> glGetUniformLocation(glamor_priv->finish_access_prog[1], @@ -240,7 +291,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen) glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler"); dispatch->glUseProgram(glamor_priv->finish_access_prog[1]); - dispatch->glUniform1i(glamor_priv->finish_access_no_revert[1], 1); + dispatch->glUniform1i(glamor_priv->finish_access_revert[1], 0); dispatch->glUniform1i(sampler_uniform_location, 0); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1], 0); dispatch->glUseProgram(0); diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index d212bd4a2..b15450a6d 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -62,18 +62,6 @@ inline static int cache_hbucket(int size) order = CACHE_BUCKET_HCOUNT - 1; return order; } -inline static int cache_format(GLenum format) -{ - switch (format) { -#if 0 - case GL_ALPHA: - return 1; -#endif - case GL_RGBA: - default: - return 0; - } -} glamor_pixmap_fbo * glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, @@ -82,23 +70,27 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry; int size; + int n_format; #ifdef NO_FBO_CACHE return NULL; #else + n_format = cache_format(format); + if (n_format == -1) + return NULL; if (!(flag & GLAMOR_CACHE_TEXTURE)) - cache = &glamor_priv->fbo_cache[cache_format(format)] + cache = &glamor_priv->fbo_cache[n_format] [cache_wbucket(w)] [cache_hbucket(h)]; else - cache = &glamor_priv->tex_cache[cache_format(format)] + cache = &glamor_priv->tex_cache[n_format] [cache_wbucket(w)] [cache_hbucket(h)]; if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) { xorg_list_for_each_entry(fbo_entry, cache, list) { if (fbo_entry->width >= w && fbo_entry->height >= h) { - DEBUGF("Request w %d h %d \n", w, h); - DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", + DEBUGF("Request w %d h %d format %x \n", w, h, format); + DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n", fbo_entry, fbo_entry->width, fbo_entry->height, fbo_entry->fb, fbo_entry->tex); xorg_list_del(&fbo_entry->list); @@ -110,10 +102,11 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, xorg_list_for_each_entry(fbo_entry, cache, list) { if (fbo_entry->width == w && fbo_entry->height == h) { - DEBUGF("Request w %d h %d \n", w, h); - DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", + DEBUGF("Request w %d h %d format %x \n", w, h, format); + DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n", fbo_entry, fbo_entry->width, fbo_entry->height, - fbo_entry->fb, fbo_entry->tex); + fbo_entry->fb, fbo_entry->tex, fbo_entry->format); + assert(format == fbo_entry->format); xorg_list_del(&fbo_entry->list); return fbo_entry; } @@ -144,21 +137,25 @@ static void glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) { struct xorg_list *cache; + int n_format; + #ifdef NO_FBO_CACHE glamor_purge_fbo(fbo); return; #else - if (fbo->fb == 0) { + n_format = cache_format(fbo->format); + + if (fbo->fb == 0 || n_format == -1) { glamor_purge_fbo(fbo); return; } if (fbo->fb) - cache = &fbo->glamor_priv->fbo_cache[cache_format(fbo->format)] + cache = &fbo->glamor_priv->fbo_cache[n_format] [cache_wbucket(fbo->width)] [cache_hbucket(fbo->height)]; else - cache = &fbo->glamor_priv->tex_cache[cache_format(fbo->format)] + cache = &fbo->glamor_priv->tex_cache[n_format] [cache_wbucket(fbo->width)] [cache_hbucket(fbo->height)]; DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, @@ -170,17 +167,15 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, - int w, int h, int depth, GLint tex, int flag) + int w, int h, GLenum format, GLint tex, int flag) { glamor_pixmap_fbo *fbo; - GLenum format; fbo = calloc(1, sizeof(*fbo)); if (fbo == NULL) return NULL; xorg_list_init(&fbo->list); - gl_iformat_for_depth(depth, &format); fbo->tex = tex; fbo->width = w; @@ -338,19 +333,18 @@ glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, - int w, int h, int depth, int flag) + int w, int h, + GLenum format, + int flag) { glamor_gl_dispatch *dispatch; glamor_pixmap_fbo *fbo; - GLenum format; GLint tex; int cache_flag; - if (!glamor_check_fbo_size(glamor_priv, w, h) - || !glamor_check_fbo_depth(depth)) + if (!glamor_check_fbo_size(glamor_priv, w, h)) return NULL; - gl_iformat_for_depth(depth, &format); if (flag == GLAMOR_CREATE_FBO_NO_FBO) goto new_fbo; @@ -374,7 +368,7 @@ new_fbo: dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, NULL); - fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); + fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag); glamor_put_dispatch(glamor_priv); return fbo; diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index efbd1baca..b1093e8e9 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -39,10 +39,11 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, struct glamor_screen_private *glamor_priv; int x_off, y_off; GLenum tex_format, tex_type; - int no_alpha, no_revert; - PixmapPtr temp_pixmap = NULL; + int no_alpha, revert; + glamor_pixmap_fbo *temp_fbo = NULL; glamor_gl_dispatch * dispatch; Bool ret = FALSE; + int swap_rb; goto fall_back; @@ -69,7 +70,9 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, &tex_format, &tex_type, &no_alpha, - &no_revert)) { + &revert, + &swap_rb, + 0)) { glamor_fallback("unknown depth. %d \n", drawable->depth); goto fall_back; } @@ -78,14 +81,16 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, glamor_validate_pixmap(pixmap); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && (glamor_tex_format_is_readable(format) || !no_revert)) { + && ( swap_rb != SWAP_NONE_DOWNLOADING + || revert != REVERT_NONE)) { /* XXX prepare whole pixmap is not efficient. */ - temp_pixmap = - glamor_es2_pixmap_read_prepare(pixmap, &tex_format, - &tex_type, no_alpha, - no_revert); - pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); + temp_fbo = + glamor_es2_pixmap_read_prepare(pixmap, tex_format, + tex_type, no_alpha, + revert, swap_rb); + if (temp_fbo == NULL) + goto fall_back; + } int row_length = PixmapBytePad(w, drawable->depth); @@ -113,8 +118,8 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, tex_format, tex_type, d); glamor_put_dispatch(glamor_priv); - if (temp_pixmap) - glamor_destroy_pixmap(temp_pixmap); + if (temp_fbo) + glamor_destroy_fbo(temp_fbo); ret = TRUE; diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 91030a3d4..8341df42e 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -35,17 +35,18 @@ _glamor_get_spans(DrawablePtr drawable, { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); GLenum format, type; - int no_alpha, no_revert; + int no_alpha, revert; glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_gl_dispatch *dispatch; - PixmapPtr temp_pixmap = NULL; + glamor_pixmap_fbo *temp_fbo = NULL; int i; uint8_t *readpixels_dst = (uint8_t *) dst; int x_off, y_off; Bool ret = FALSE; + int swap_rb; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); @@ -55,24 +56,29 @@ _glamor_get_spans(DrawablePtr drawable, if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, &no_alpha, - &no_revert)) { + &revert, &swap_rb, 0)) { glamor_fallback("unknown depth. %d \n", drawable->depth); goto fail; } + if (revert > REVERT_NORMAL) + goto fail; + glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && (!glamor_tex_format_is_readable(format) || !no_revert)) { + && ( swap_rb != SWAP_NONE_DOWNLOADING + || revert != REVERT_NONE)) { /* XXX prepare whole pixmap is not efficient. */ - temp_pixmap = - glamor_es2_pixmap_read_prepare(pixmap, &format, - &type, no_alpha, - no_revert); - pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); + temp_fbo = + glamor_es2_pixmap_read_prepare(pixmap, format, + type, no_alpha, + revert, swap_rb); + if (temp_fbo == NULL) + goto fail; + } glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); @@ -94,8 +100,8 @@ _glamor_get_spans(DrawablePtr drawable, PixmapBytePad(widths[i], drawable->depth); } glamor_put_dispatch(glamor_priv); - if (temp_pixmap) - glamor_destroy_pixmap(temp_pixmap); + if (temp_fbo) + glamor_destroy_fbo(temp_fbo); ret = TRUE; goto done; @@ -105,6 +111,7 @@ fail: && glamor_ddx_fallback_check_pixmap(drawable)) goto done; + ret = TRUE; glamor_fallback("from %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 7f4a90b81..0570a9aaa 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -89,10 +89,10 @@ glamor_validate_pixmap(PixmapPtr pixmap) } void -glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) +glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo) { - glamor_gl_dispatch *dispatch = glamor_get_dispatch(pixmap_priv->glamor_priv); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fbo->fb); + glamor_gl_dispatch *dispatch = glamor_get_dispatch(fbo->glamor_priv); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); #ifndef GLAMOR_GLES2 dispatch->glMatrixMode(GL_PROJECTION); dispatch->glLoadIdentity(); @@ -100,10 +100,16 @@ glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) dispatch->glLoadIdentity(); #endif dispatch->glViewport(0, 0, - pixmap_priv->fbo->width, - pixmap_priv->fbo->height); + fbo->width, + fbo->height); - glamor_put_dispatch(pixmap_priv->glamor_priv); + glamor_put_dispatch(fbo->glamor_priv); +} + +void +glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) +{ + glamor_set_destination_pixmap_fbo(pixmap_priv->fbo); } int @@ -280,9 +286,8 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, * */ static void -_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, int no_alpha, int no_revert, - int flip) +_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, + int no_alpha, int revert, int swap_rb) { glamor_pixmap_private *pixmap_priv = @@ -308,7 +313,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, if (!pixmap_priv) return; - need_flip = (flip && !glamor_priv->yInverted); + need_flip = !glamor_priv->yInverted; glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD, "Uploading pixmap %p %dx%d depth%d.\n", @@ -319,7 +324,11 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ - if (no_alpha == 0 && no_revert == 1 && !need_flip) { + if (no_alpha == 0 + && revert == REVERT_NONE + && swap_rb == SWAP_NONE_UPLOADING + && !need_flip) { + __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->fbo->tex, 1); return; @@ -365,10 +374,10 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, #endif dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUniform1i(glamor_priv-> - finish_access_no_revert[no_alpha], - no_revert); + finish_access_revert[no_alpha], + revert); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], - 0); + swap_rb); dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -441,18 +450,22 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) * 2. no_alpha != 0, we need to wire the alpha. * */ static int -glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) +glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int revert, int swap_rb) { int flag; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; - GLenum format; glamor_pixmap_fbo *fbo; + GLenum iformat; pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - if (!(no_alpha || !no_revert || !glamor_priv->yInverted)) { + if (!(no_alpha + || (revert != REVERT_NONE) + || (swap_rb != SWAP_NONE_UPLOADING) + || !glamor_priv->yInverted)) { + /* We don't need a fbo, a simple texture uploading should work. */ if (pixmap_priv && pixmap_priv->fbo) return 0; @@ -464,9 +477,15 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) flag = 0; } + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + gl_iformat_for_depth(pixmap->drawable.depth, &iformat); + else + iformat = format; + + fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth, + iformat, flag); if (fbo == NULL) { glamor_fallback @@ -485,20 +504,24 @@ enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap) { GLenum format, type; - int no_alpha, no_revert; + int no_alpha, revert, swap_rb; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, - &type, &no_alpha, - &no_revert)) { + &type, + &no_alpha, + &revert, + &swap_rb, 1)) { glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); return GLAMOR_UPLOAD_FAILED; } - if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert)) + + if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) return GLAMOR_UPLOAD_FAILED; + _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - no_revert, 1); + revert, swap_rb); return GLAMOR_UPLOAD_DONE; } @@ -523,21 +546,19 @@ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap) { GLenum format, type; - int no_alpha, no_revert; + int no_alpha, revert, swap_rb; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, &no_alpha, - &no_revert)) { + &revert, &swap_rb, 1)) { ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); assert(0); } - in_restore = 1; _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - no_revert, 1); - in_restore = 0; + revert, swap_rb); } /* @@ -548,65 +569,56 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap) * get a new temporary pixmap returned. * */ -PixmapPtr -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, - GLenum * type, int no_alpha, int no_revert) +glamor_pixmap_fbo * +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, + GLenum type, int no_alpha, int revert, int swap_rb) + { glamor_pixmap_private *source_priv; glamor_screen_private *glamor_priv; ScreenPtr screen; - PixmapPtr temp_pixmap; - glamor_pixmap_private *temp_pixmap_priv; + glamor_pixmap_fbo *temp_fbo; glamor_gl_dispatch *dispatch; - static float vertices[8] = { -1, -1, - 1, -1, - 1, 1, - -1, 1 - }; - static float texcoords[8] = { 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - int swap_rb = 0; + float temp_xscale, temp_yscale, source_xscale, source_yscale; + static float vertices[8]; + static float texcoords[8]; screen = source->drawable.pScreen; glamor_priv = glamor_get_screen_private(screen); source_priv = glamor_get_pixmap_private(source); - if (*format == GL_BGRA) { - *format = GL_RGBA; - swap_rb = 1; - } - - - temp_pixmap = glamor_create_pixmap (screen, - source->drawable.width, - source->drawable.height, - source->drawable.depth, 0); - - temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + temp_fbo = glamor_create_fbo(glamor_priv, + source->drawable.width, + source->drawable.height, + format, + 0); + if (temp_fbo == NULL) + return NULL; dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); + temp_xscale = 1.0 / temp_fbo->width; + temp_yscale = 1.0 / temp_fbo->height; - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, - source->drawable.width, - source->drawable.height, 0, *format, *type, - NULL); + glamor_set_normalize_vcoords(temp_xscale, + temp_yscale, + 0, 0, + source->drawable.width, source->drawable.height, + glamor_priv->yInverted, + vertices); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale); + glamor_set_normalize_tcoords(source_xscale, + source_yscale, + 0, 0, + source->drawable.width, source->drawable.height, + glamor_priv->yInverted, + texcoords); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texcoords); @@ -621,12 +633,11 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); - + glamor_set_destination_pixmap_fbo(temp_fbo); dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUniform1i(glamor_priv-> - finish_access_no_revert[no_alpha], - no_revert); + finish_access_revert[no_alpha], + revert); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb); @@ -636,7 +647,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(0); glamor_put_dispatch(glamor_priv); - return temp_pixmap; + return temp_fbo; } @@ -656,21 +667,23 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_get_pixmap_private(pixmap); unsigned int stride, row_length, y; GLenum format, type, gl_access, gl_usage; - int no_alpha, no_revert; + int no_alpha, revert, swap_rb; uint8_t *data = NULL, *read; - PixmapPtr temp_pixmap = NULL; ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *temp_fbo = NULL; screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, - &type, &no_alpha, - &no_revert)) { + &type, + &no_alpha, + &revert, + &swap_rb, 0)) { ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth); assert(0); // Should never happen. @@ -692,11 +705,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_validate_pixmap(pixmap); if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && (!glamor_tex_format_is_readable(format) || !no_revert)) { - temp_pixmap = - glamor_es2_pixmap_read_prepare(pixmap, &format, - &type, no_alpha, - no_revert); + && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { + if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, format, + type, no_alpha, + revert, swap_rb))) + return FALSE; } switch (access) { case GLAMOR_ACCESS_RO: @@ -807,8 +820,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; pixmap->devPrivate.ptr = data; - if (temp_pixmap) - glamor_destroy_pixmap(temp_pixmap); + if (temp_fbo != NULL) + glamor_destroy_fbo(temp_fbo); return TRUE; } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 54bbdb1ab..828b08ea0 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -182,7 +182,12 @@ struct glamor_saved_procs { UnrealizeGlyphProcPtr unrealize_glyph; }; +#ifdef GLAMOR_GLES2 +#define CACHE_FORMAT_COUNT 3 +#else #define CACHE_FORMAT_COUNT 1 +#endif + #define CACHE_BUCKET_WCOUNT 4 #define CACHE_BUCKET_HCOUNT 4 @@ -221,7 +226,7 @@ typedef struct glamor_screen_private { /* shaders to restore a texture to another texture.*/ GLint finish_access_prog[2]; - GLint finish_access_no_revert[2]; + GLint finish_access_revert[2]; GLint finish_access_swap_rb[2]; /* glamor_tile */ @@ -395,9 +400,9 @@ Bool glamor_destroy_pixmap(PixmapPtr pixmap); glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv); void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo); glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, - int w, int h, int depth, GLint tex, int flag); + int w, int h, GLenum format, GLint tex, int flag); glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, - int w, int h, int depth, int flag); + int w, int h, GLenum format, int flag); void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); void glamor_purge_fbo(glamor_pixmap_fbo *fbo); @@ -451,6 +456,7 @@ void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, int glamor_set_destination_pixmap(PixmapPtr pixmap); int glamor_set_destination_pixmap_priv(glamor_pixmap_private * pixmap_priv); +void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *); /* nc means no check. caller must ensure this pixmap has valid fbo. * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly. @@ -458,10 +464,9 @@ int glamor_set_destination_pixmap_priv(glamor_pixmap_private * void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv); - -PixmapPtr -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, - GLenum * type, int no_alpha, int no_revert); +glamor_pixmap_fbo * +glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, + GLenum type, int no_alpha, int revert, int swap_rb); void glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 75e5b4cdd..e38c45aba 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -264,8 +264,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, float vertices[8], texcoords[8]; GLfloat xscale, yscale, txscale, tyscale; GLuint tex; - int no_alpha, no_revert; + int no_alpha, revert; Bool ret = FALSE; + int swap_rb; if (image_format == XYBitmap) { assert(depth == 1); @@ -289,7 +290,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, &no_alpha, - &no_revert)) { + &revert, + &swap_rb, + 1)) { glamor_fallback("unknown depth. %d \n", drawable->depth); goto fail; } @@ -341,10 +344,10 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, #endif dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUniform1i(glamor_priv-> - finish_access_no_revert[no_alpha], - no_revert); + finish_access_revert[no_alpha], + revert); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], - 0); + swap_rb); x += drawable->x; y += drawable->y; diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index a9471698a..b6847a908 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -38,12 +38,13 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_get_screen_private(drawable->pScreen); glamor_gl_dispatch *dispatch; GLenum format, type; - int no_alpha, no_revert, i; + int no_alpha, revert, i; uint8_t *drawpixels_src = (uint8_t *) src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; Bool ret = FALSE; + int swap_rb; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { @@ -59,7 +60,9 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, &format, &type, &no_alpha, - &no_revert)) { + &revert, + &swap_rb, + 1)) { glamor_fallback("unknown depth. %d \n", drawable->depth); goto fail; } diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 29b7b12b8..35e8d612e 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -194,14 +194,14 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) && (_w_) < _glamor_->max_fbo_size \ && (_h_) < _glamor_->max_fbo_size) -#define glamor_check_fbo_depth(_depth_) ( \ - _depth_ == 8 \ - || _depth_ == 15 \ - || _depth_ == 16 \ - || _depth_ == 24 \ - || _depth_ == 30 \ - || _depth_ == 32) - +/* For 1bpp pixmap, we don't store it as texture. */ +#define glamor_check_pixmap_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 && pixmap_priv->is_picture == 1) #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) @@ -286,6 +286,14 @@ format_for_pixmap(PixmapPtr pixmap) return pict_format; } + +#define REVERT_NONE 0 +#define REVERT_NORMAL 1 +#define SWAP_NONE_DOWNLOADING 0 +#define SWAP_DOWNLOADING 1 +#define SWAP_UPLOADING 2 +#define SWAP_NONE_UPLOADING 3 + /* * Map picture's format to the correct gl texture format and type. * no_alpha is used to indicate whehter we need to wire alpha to 1. @@ -297,10 +305,15 @@ static inline int glamor_get_tex_format_type_from_pictformat(PictFormatShort format, GLenum * tex_format, GLenum * tex_type, - int *no_alpha, int *no_revert) + int *no_alpha, + int *revert, + int *swap_rb, + int is_upload) + { *no_alpha = 0; - *no_revert = 1; + *revert = REVERT_NONE; + *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; switch (format) { case PICT_a1: *tex_format = GL_COLOR_INDEX; @@ -385,6 +398,18 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, } return 0; } + +/* Currently, we use RGBA to represent all formats. */ +inline static int cache_format(GLenum format) +{ + switch (format) { + case GL_RGBA: + return 0; + default: + return -1; + } +} + #else #define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) @@ -392,25 +417,32 @@ static inline int glamor_get_tex_format_type_from_pictformat(PictFormatShort format, GLenum * tex_format, GLenum * tex_type, - int *no_alpha, int *no_revert) + int *no_alpha, + int *revert, + int *swap_rb, + int is_upload) { + int need_swap_rb = 0; + *no_alpha = 0; - *no_revert = IS_LITTLE_ENDIAN; + *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL; switch (format) { case PICT_b8g8r8x8: *no_alpha = 1; case PICT_b8g8r8a8: - *tex_format = GL_BGRA; + *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_BYTE; - *no_revert = !IS_LITTLE_ENDIAN; + need_swap_rb = 1; + *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; break; case PICT_x8r8g8b8: *no_alpha = 1; case PICT_a8r8g8b8: - *tex_format = GL_BGRA; + *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_BYTE; + need_swap_rb = 1; break; case PICT_x8b8g8r8: @@ -425,7 +457,7 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, case PICT_a2r10g10b10: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *no_revert = TRUE; + *revert = REVERT_NONE; break; case PICT_x2b10g10r10: @@ -433,19 +465,20 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, case PICT_a2b10g10r10: *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *no_revert = TRUE; + *revert = REVERT_NONE; break; case PICT_r5g6b5: *tex_format = GL_RGB; *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *no_revert = TRUE; + *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL; + break; case PICT_b5g6r5: *tex_format = GL_RGB; *tex_type = GL_UNSIGNED_SHORT_5_6_5; - *no_revert = FALSE; + need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;; break; case PICT_x1b5g5r5: @@ -453,7 +486,7 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, case PICT_a1b5g5r5: *tex_format = GL_RGBA; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *no_revert = TRUE; + *revert = REVERT_NONE; break; case PICT_x1r5g5b5: @@ -461,29 +494,30 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, case PICT_a1r5g5b5: *tex_format = GL_BGRA; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *no_revert = TRUE; + *revert = REVERT_NONE; break; case PICT_a8: *tex_format = GL_ALPHA; *tex_type = GL_UNSIGNED_BYTE; - *no_revert = TRUE; + *revert = REVERT_NONE; break; case PICT_x4r4g4b4: *no_alpha = 1; case PICT_a4r4g4b4: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - *no_revert = TRUE; + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; + *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; + need_swap_rb = 1; break; case PICT_x4b4g4r4: *no_alpha = 1; case PICT_a4b4g4r4: *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - *no_revert = TRUE; + *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; + *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE; break; default: @@ -492,9 +526,27 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, format); return -1; } + + if (need_swap_rb) + *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING; + else + *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; return 0; } +inline static int cache_format(GLenum format) +{ + switch (format) { + case GL_ALPHA: + return 2; + case GL_RGB: + return 1; + case GL_RGBA: + return 0; + default: + return -1; + } +} #endif @@ -503,7 +555,10 @@ static inline int glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, GLenum * format, GLenum * type, - int *no_alpha, int *no_revert) + int *no_alpha, + int *revert, + int *swap_rb, + int is_upload) { glamor_pixmap_private *pixmap_priv; PictFormatShort pict_format; @@ -517,7 +572,9 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, return glamor_get_tex_format_type_from_pictformat(pict_format, format, type, no_alpha, - no_revert); + revert, + swap_rb, + is_upload); } From 0650c7d4be6d4c21510c953543599aea32780f24 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 5 Apr 2012 22:31:44 +0800 Subject: [PATCH 318/462] gles2: Added 1555/2101010 formats support. Added color conversion code to support 1555/2101010 formats,now gles2 can pass the render check with all formats. We use 5551 to represent 1555, and do the revertion if downloading/uploading is needed. For 2101010, as gles2 doesn't support reading the identical formats. We have to use 8888 to represent, thus we may introduce some accurate problem. But anyway, we can pass the error checking in render check, so that may not be a big problem. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 373 ++++++++++++++++++++++++++++++++++------- glamor/glamor_priv.h | 10 +- glamor/glamor_utils.h | 74 ++++++-- 3 files changed, 382 insertions(+), 75 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 0570a9aaa..4e8d6b885 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -210,8 +210,202 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) #endif } +void * +_glamor_color_convert_a1_a8(void *src_bits, int w, int h, int stride, int revert) +{ + void *bits; + PictFormatShort dst_format, src_format; + pixman_image_t *dst_image; + pixman_image_t *src_image; + if (revert == REVERT_UPLOADING_A1) { + src_format = PICT_a1; + dst_format = PICT_a8; + } else { + dst_format = PICT_a1; + src_format = PICT_a8; + } + bits = malloc(stride * h); + if (bits == NULL) + return NULL; + dst_image = pixman_image_create_bits(dst_format, + w, h, + bits, + stride); + if (dst_image == NULL) { + free(bits); + return NULL; + } + + src_image = pixman_image_create_bits(src_format, + w, h, + src_bits, + stride); + + if (src_image == NULL) { + pixman_image_unref(dst_image); + free(bits); + return NULL; + } + + pixman_image_composite(PictOpSrc, src_image, NULL, dst_image, + 0, 0, 0, 0, 0, 0, + w,h); + + pixman_image_unref(src_image); + pixman_image_unref(dst_image); + return bits; +} + +#define ADJUST_BITS(d, src_bits, dst_bits) (((dst_bits) == (src_bits)) ? (d) : \ + (((dst_bits) > (src_bits)) ? \ + (((d) << ((dst_bits) - (src_bits))) \ + + (( 1 << ((dst_bits) - (src_bits))) >> 1)) \ + : ((d) >> ((src_bits) - (dst_bits))))) + +#define GLAMOR_DO_CONVERT(src, dst, no_alpha, swap, \ + a_shift_src, a_bits_src, \ + b_shift_src, b_bits_src, \ + g_shift_src, g_bits_src, \ + r_shift_src, r_bits_src, \ + a_shift, a_bits, \ + b_shift, b_bits, \ + g_shift, g_bits, \ + r_shift, r_bits) \ + { \ + typeof(src) a,b,g,r; \ + typeof(src) a_mask_src, b_mask_src, g_mask_src, r_mask_src;\ + a_mask_src = (((1 << (a_bits_src)) - 1) << a_shift_src);\ + b_mask_src = (((1 << (b_bits_src)) - 1) << b_shift_src);\ + g_mask_src = (((1 << (g_bits_src)) - 1) << g_shift_src);\ + r_mask_src = (((1 << (r_bits_src)) - 1) << r_shift_src);\ + if (no_alpha) \ + a = (a_mask_src) >> (a_shift_src); \ + else \ + a = ((src) & (a_mask_src)) >> (a_shift_src); \ + b = ((src) & (b_mask_src)) >> (b_shift_src); \ + g = ((src) & (g_mask_src)) >> (g_shift_src); \ + r = ((src) & (r_mask_src)) >> (r_shift_src); \ + a = ADJUST_BITS(a, a_bits_src, a_bits); \ + b = ADJUST_BITS(b, b_bits_src, b_bits); \ + g = ADJUST_BITS(g, g_bits_src, g_bits); \ + r = ADJUST_BITS(r, r_bits_src, r_bits); \ + if (swap == 0) \ + (*dst) = ((a) << (a_shift)) | ((b) << (b_shift)) | ((g) << (g_shift)) | ((r) << (r_shift)); \ + else \ + (*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \ + } + +void * +_glamor_color_revert_x2b10g10r10(void *src_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) +{ + int x,y; + unsigned int *words, *saved_words, *source_words; + int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || swap_rb == SWAP_NONE_UPLOADING); + + words = malloc(stride * h); + source_words = src_bits; + if (words == NULL) + return NULL; + saved_words = words; + + for (y = 0; y < h; y++) + { + DEBUGF("Line %d : ", y); + for (x = 0; x < w; x++) + { + unsigned int pixel = source_words[x]; + + if (revert == REVERT_DOWNLOADING_2_10_10_10) + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 24, 8, 16, 8, 8, 8, 0, 8, + 30, 2, 20, 10, 10, 10, 0, 10) + else + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 30, 2, 20, 10, 10, 10, 0, 10, + 24, 8, 16, 8, 8, 8, 0, 8); + DEBUGF("%x:%x ", pixel, words[x]); + } + DEBUGF("\n"); + words += stride / sizeof(*words); + source_words += stride / sizeof(*words); + } + DEBUGF("\n"); + return saved_words; + +} + +void * +_glamor_color_revert_x1b5g5r5(void *src_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) +{ + int x,y; + unsigned short *words, *saved_words, *source_words; + int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || swap_rb == SWAP_NONE_UPLOADING); + + words = malloc(stride * h); + source_words = src_bits; + if (words == NULL) + return NULL; + saved_words = words; + + for (y = 0; y < h; y++) + { + DEBUGF("Line %d : ", y); + for (x = 0; x < w; x++) + { + unsigned short pixel = source_words[x]; + + if (revert == REVERT_DOWNLOADING_1_5_5_5) + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 0, 1, 1, 5, 6, 5, 11, 5, + 15, 1, 10, 5, 5, 5, 0, 5) + else + GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap, + 15, 1, 10, 5, 5, 5, 0, 5, + 0, 1, 1, 5, 6, 5, 11, 5); + DEBUGF("%04x:%04x ", pixel, words[x]); + } + DEBUGF("\n"); + words += stride / sizeof(*words); + source_words += stride / sizeof(*words); + } + DEBUGF("\n"); + return saved_words; +} + +/* + * This function is to convert an unsupported color format to/from a + * supported GL format. + * Here are the current scenarios: + * + * @no_alpha: + * If it is set, then we need to wire the alpha value to 1. + * @revert: + REVERT_DOWNLOADING_A1 : convert an Alpha8 buffer to a A1 buffer. + REVERT_UPLOADING_A1 : convert an A1 buffer to an Alpha8 buffer + REVERT_DOWNLOADING_2_10_10_10 : convert r10G10b10X2 to X2B10G10R10 + REVERT_UPLOADING_2_10_10_10 : convert X2B10G10R10 to R10G10B10X2 + REVERT_DOWNLOADING_1_5_5_5 : convert B5G5R5X1 to X1R5G5B5 + REVERT_UPLOADING_1_5_5_5 : convert X1R5G5B5 to B5G5R5X1 + @swap_rb: if we have the swap_rb set, then we need to swap the R and B's position. + * + */ + +void * +glamor_color_convert_to_bits(void *src_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) +{ + if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) { + return _glamor_color_convert_a1_a8(src_bits, w, h, stride, revert); + } else if (revert == REVERT_DOWNLOADING_2_10_10_10 || revert == REVERT_UPLOADING_2_10_10_10) { + return _glamor_color_revert_x2b10g10r10(src_bits, w, h, stride, no_alpha, revert, swap_rb); + } else if (revert == REVERT_DOWNLOADING_1_5_5_5 || revert == REVERT_UPLOADING_1_5_5_5) { + return _glamor_color_revert_x1b5g5r5(src_bits, w, h, stride, no_alpha, revert, swap_rb); + } else + ErrorF("convert a non-supported mode %x.\n", revert); + + return NULL; +} /** * Upload pixmap to a specified texture. @@ -220,7 +414,8 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) int in_restore = 0; static void __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, GLuint tex, int sub) + GLenum type, GLuint tex, int sub, + void *bits) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -228,7 +423,6 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; unsigned int stride, row_length; - void *texels; GLenum iformat; if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) @@ -253,47 +447,35 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } - if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) { - texels = NULL; + if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixmap_priv->fbo->pbo); - } else - texels = pixmap->devPrivate.ptr; if (sub) dispatch->glTexSubImage2D(GL_TEXTURE_2D, 0,0,0, pixmap->drawable.width, pixmap->drawable.height, format, type, - texels); + bits); else dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, pixmap->drawable.width, pixmap->drawable.height, 0, format, type, - texels); + bits); - if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) + if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glamor_put_dispatch(glamor_priv); } - -/* - * 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 no_alpha, int revert, int swap_rb) +Bool +glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type, + int no_alpha, int revert, int swap_rb, void *bits) { - - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; static float vertices[8]; static float texcoords[8] = { 0, 1, @@ -310,28 +492,40 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, float dst_xscale, dst_yscale; GLuint tex; int need_flip; + int need_free_bits = 0; - if (!pixmap_priv) - return; need_flip = !glamor_priv->yInverted; - 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); + if (bits == NULL) + goto ready_to_upload; + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && revert > REVERT_NORMAL) { + bits = glamor_color_convert_to_bits(bits, pixmap->drawable.width, + pixmap->drawable.height, + pixmap->devKind, + no_alpha, revert, swap_rb); + if (bits == NULL) { + ErrorF("Failed to convert pixmap no_alpha %d, revert mode %d, swap mode %d\n", swap_rb); + return FALSE; + } + no_alpha = 0; + revert = REVERT_NONE; + swap_rb = SWAP_NONE_UPLOADING; + need_free_bits = TRUE; + } + +ready_to_upload: /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ if (no_alpha == 0 && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip) { - __glamor_upload_pixmap_to_texture(pixmap, format, type, - pixmap_priv->fbo->tex, 1); - return; + pixmap_priv->fbo->tex, 1, + bits); + return TRUE; } if (need_flip) @@ -361,7 +555,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, glamor_set_destination_pixmap_priv_nc(pixmap_priv); dispatch->glGenTextures(1, &tex); - __glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0); + __glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0, bits); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -391,6 +585,43 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); glamor_put_dispatch(glamor_priv); + + if (need_free_bits) + free(bits); + return TRUE; +} + +/* + * Load texture from the pixmap's data pointer and then + * draw the texture to the fbo, and flip the y axis. + * */ + +static Bool +_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, + GLenum type, int no_alpha, int revert, + int swap_rb) +{ + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + void *bits; + int need_free_bits = 0; + + if (!pixmap_priv) + return TRUE; + + 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); + + if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) + bits = NULL; + + return glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, + revert, swap_rb, + pixmap->devPrivate.ptr); } void @@ -442,7 +673,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) glamor_put_dispatch(fbo->glamor_priv); } -/* +/* * Prepare to upload a pixmap to texture memory. * no_alpha equals 1 means the format needs to wire alpha to 1. * Two condtion need to setup a fbo for a pixmap @@ -520,28 +751,15 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) return GLAMOR_UPLOAD_FAILED; - _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - revert, swap_rb); + if (_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, + revert, swap_rb)) + return GLAMOR_UPLOAD_DONE; + else + return GLAMOR_UPLOAD_FAILED; + 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) { @@ -557,14 +775,16 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap) assert(0); } - _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - revert, swap_rb); + if (!_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, + revert, swap_rb)) + LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n", + pixmap->drawable.pScreen->myNum); } -/* +/* * as gles2 only support a very small set of color format and - * type when do glReadPixel, - * Before we use glReadPixels to get back a textured pixmap, + * type when do glReadPixel, + * Before we use glReadPixels to get back a textured pixmap, * Use shader to convert it to a supported format and thus * get a new temporary pixmap returned. * */ @@ -654,7 +874,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, /** * 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 + * 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. @@ -674,6 +894,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; glamor_pixmap_fbo *temp_fbo = NULL; + int need_post_conversion = 0; screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) @@ -704,7 +925,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) * we can just validate it on CPU. */ glamor_validate_pixmap(pixmap); + + need_post_conversion = (revert > REVERT_NORMAL); + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && !need_post_conversion && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, format, type, no_alpha, @@ -775,8 +1000,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); } else { - if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) - type = GL_UNSIGNED_SHORT_5_5_5_1; dispatch->glReadPixels(0, 0, pixmap->drawable.width, pixmap->drawable.height, @@ -815,6 +1038,30 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); glamor_put_dispatch(glamor_priv); + + if (need_post_conversion) { + /* As OpenGL desktop version never enters here. + * Don't need to consider if the pbo is valid.*/ + char *new_data; + int stride; + assert(pixmap_priv->fbo->pbo_valid == 0); + + /* Only A1 <--> A8 conversion need to adjust the stride value. */ + if (pixmap->drawable.depth == 1) + stride = (((pixmap->drawable.width * 8 + 7) / 8) + 3) & ~3; + else + stride = pixmap->devKind; + new_data = glamor_color_convert_to_bits(data, pixmap->drawable.width, + pixmap->drawable.height, + stride, no_alpha, + revert, swap_rb); + free(data); + if (new_data == NULL) { + return FALSE; + } + data = new_data; + } + done: pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 828b08ea0..71d5bf007 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -633,13 +633,21 @@ void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo); 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); +/** + * Upload bits to a pixmap's texture. This function will + * convert the bits to the specified format/type format + * if the conversion is unavoidable. + **/ +Bool glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type, + int no_alpha, int revert, int swap_rb, void *bits); + /** * Destroy all the resources allocated on the uploading * phase, includs the tex and fbo. diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 35e8d612e..972918c08 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -286,9 +286,17 @@ format_for_pixmap(PixmapPtr pixmap) return pict_format; } - #define REVERT_NONE 0 #define REVERT_NORMAL 1 +#define REVERT_DOWNLOADING_A1 2 +#define REVERT_UPLOADING_A1 3 +#define REVERT_DOWNLOADING_2_10_10_10 4 +#define REVERT_UPLOADING_2_10_10_10 5 +#define REVERT_DOWNLOADING_1_5_5_5 7 +#define REVERT_UPLOADING_1_5_5_5 8 +#define REVERT_DOWNLOADING_10_10_10_2 9 +#define REVERT_UPLOADING_10_10_10_2 10 + #define SWAP_NONE_DOWNLOADING 0 #define SWAP_DOWNLOADING 1 #define SWAP_UPLOADING 2 @@ -455,17 +463,48 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, case PICT_x2r10g10b10: *no_alpha = 1; case PICT_a2r10g10b10: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *revert = REVERT_NONE; + *tex_format = GL_RGBA; + /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2. + * we have to use GL_UNSIGNED_BYTE and do the conversion in + * shader latter.*/ + *tex_type = GL_UNSIGNED_BYTE; + if (is_upload == 1) { + if (!IS_LITTLE_ENDIAN) + *revert = REVERT_UPLOADING_10_10_10_2; + else + *revert = REVERT_UPLOADING_2_10_10_10; + } + else { + if (!IS_LITTLE_ENDIAN) { + *revert = REVERT_DOWNLOADING_10_10_10_2; + } + else { + *revert = REVERT_DOWNLOADING_2_10_10_10; + } + } + need_swap_rb = 1; + break; case PICT_x2b10g10r10: *no_alpha = 1; case PICT_a2b10g10r10: *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_INT_10_10_10_2; - *revert = REVERT_NONE; + *tex_type = GL_UNSIGNED_BYTE; + if (is_upload == 1) { + if (!IS_LITTLE_ENDIAN) + *revert = REVERT_UPLOADING_10_10_10_2; + else + *revert = REVERT_UPLOADING_2_10_10_10; + } + else { + if (!IS_LITTLE_ENDIAN) { + *revert = REVERT_DOWNLOADING_10_10_10_2; + } + else { + *revert = REVERT_DOWNLOADING_2_10_10_10; + } + } break; case PICT_r5g6b5: @@ -485,16 +524,29 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, *no_alpha = 1; case PICT_a1b5g5r5: *tex_format = GL_RGBA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *revert = REVERT_NONE; + *tex_type = GL_UNSIGNED_SHORT_5_5_5_1; + if (IS_LITTLE_ENDIAN) { + *revert = is_upload ? REVERT_UPLOADING_1_5_5_5 : REVERT_DOWNLOADING_1_5_5_5; + } else + *revert = REVERT_NONE; break; case PICT_x1r5g5b5: *no_alpha = 1; case PICT_a1r5g5b5: - *tex_format = GL_BGRA; - *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *revert = REVERT_NONE; + *tex_format = GL_RGBA; + *tex_type = GL_UNSIGNED_SHORT_5_5_5_1; + if (IS_LITTLE_ENDIAN) { + *revert = is_upload ? REVERT_UPLOADING_1_5_5_5 : REVERT_DOWNLOADING_1_5_5_5; + } else + *revert = REVERT_NONE; + need_swap_rb = 1; + break; + + case PICT_a1: + *tex_format = GL_ALPHA; + *tex_type = GL_UNSIGNED_BYTE; + *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1; break; case PICT_a8: From 1a238e89f39fd5aeaf6975399971123cd3e15f24 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 5 Apr 2012 22:39:41 +0800 Subject: [PATCH 319/462] glamor_putimage: Reuse the function in pixmap.c to do the uploading. We reuse glamor_upload_bits_to_pixmap_texture to do the data uploading to texture in putimage. Besides to avoid duplicate code, this also fixed the potential problem when the data format need extra reversion which is not supported by the finish shader, as glamor_upload_bits_to_pixmap_texture will handle all conditions. Tested-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_putimage.c | 61 +++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index e38c45aba..d270cae59 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -267,6 +267,8 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int no_alpha, revert; Bool ret = FALSE; int swap_rb; + PixmapPtr temp_pixmap; + glamor_pixmap_private *temp_pixmap_priv; if (image_format == XYBitmap) { assert(depth == 1); @@ -297,7 +299,27 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, goto fail; } - /* XXX consider to reuse a function to do the following work. */ + /* create a temporary pixmap and upload the bits to that + * pixmap, then apply clip copy it to the destination pixmap.*/ + + temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); + + if (temp_pixmap == NULL) + goto fail; + temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + + if (temp_pixmap_priv->fbo == NULL) { + glamor_destroy_pixmap(temp_pixmap); + goto fail; + } + + if (!glamor_upload_bits_to_pixmap_texture(temp_pixmap, format, type, + no_alpha, revert, swap_rb, bits)) { + glamor_destroy_pixmap(temp_pixmap); + goto fail; + } + + dispatch = glamor_get_dispatch(glamor_priv); glamor_set_alu(dispatch, gc->alu); glamor_set_destination_pixmap_priv_nc(pixmap_priv); @@ -311,43 +333,18 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, GL_FALSE, 2 * sizeof(float), texcoords); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, - src_stride * 8 / - pixmap->drawable.bitsPerPixel); - } else { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } - - dispatch->glGenTextures(1, &tex); dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - iformat = format; - } else { - iformat = GL_RGBA; - } - - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, - w, h, 0, format, type, bits); - + dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); + dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); dispatch->glUniform1i(glamor_priv-> finish_access_revert[no_alpha], - revert); + REVERT_NONE); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], - swap_rb); + SWAP_NONE_UPLOADING); x += drawable->x; y += drawable->y; @@ -355,8 +352,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); clip = fbGetCompositeClip(gc); - txscale = 1.0 / w; - tyscale = 1.0 / h; + pixmap_priv_get_scale(temp_pixmap_priv, &txscale, &tyscale); pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); for (nbox = REGION_NUM_RECTS(clip), @@ -404,6 +400,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_set_planemask(pixmap, ~0); glamor_put_dispatch(glamor_priv); + glamor_destroy_pixmap(temp_pixmap); ret = TRUE; goto done; From 3e9c35bdcbdb96a67c9f2a1ea76c382aaacca7e9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 6 Apr 2012 11:02:36 +0800 Subject: [PATCH 320/462] glamor_set_alu: Fallback for non GXcopy ops with GLES2. As GLES2 doesn't support LogiOps, we have to fallback here. GLES2 programing guide's statement is as below: "In addition, LogicOp is removed as it is very infrequently used by applications and the OpenGL ES working group did not get requests from independent software vendors (ISVs) to support this feature in OpenGL ES 2.0." So, I think, fallback here may not a big deal ;). Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 6 +++++- glamor/glamor_fill.c | 5 ++++- glamor/glamor_pixmap.c | 16 +++++++++------- glamor/glamor_priv.h | 2 +- glamor/glamor_putimage.c | 6 +++++- glamor/glamor_setspans.c | 6 +++++- glamor/glamor_tile.c | 5 ++++- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index b4880378c..a373d3d0b 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -194,7 +194,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch = glamor_get_dispatch(glamor_priv); - glamor_set_alu(dispatch, alu); + if (!glamor_set_alu(dispatch, alu)) { + glamor_put_dispatch(glamor_priv); + return FALSE; + } + if (alu != GXcopy) { glamor_set_destination_pixmap_priv_nc (src_pixmap_priv); glamor_validate_pixmap(src_pixmap); diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index e8419c633..53c750afb 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -189,7 +189,10 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_validate_pixmap(pixmap); dispatch = glamor_get_dispatch(glamor_priv); - glamor_set_alu(dispatch, alu); + if (!glamor_set_alu(dispatch, alu)) { + glamor_put_dispatch(glamor_priv); + return FALSE; + } dispatch->glUseProgram(glamor_priv->solid_prog); dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 4e8d6b885..35b2d56f1 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -144,15 +144,13 @@ glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask) return GL_FALSE; } - - -void +Bool glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) { #ifndef GLAMOR_GLES2 if (alu == GXcopy) { dispatch->glDisable(GL_COLOR_LOGIC_OP); - return; + return TRUE; } dispatch->glEnable(GL_COLOR_LOGIC_OP); switch (alu) { @@ -202,12 +200,16 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) dispatch->glLogicOp(GL_SET); break; default: - FatalError("unknown logic op\n"); + glamor_fallback("unsupported alu %x\n", alu); + return FALSE; } #else - if (alu != GXcopy) - ErrorF("unsupported alu %x \n", alu); + if (alu != GXcopy) { + glamor_fallback("unsupported alu %x\n", alu); + return FALSE; + } #endif + return TRUE; } void * diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 71d5bf007..bea4f662a 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -468,7 +468,7 @@ glamor_pixmap_fbo * glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, GLenum type, int no_alpha, int revert, int swap_rb); -void glamor_set_alu(struct glamor_gl_dispatch *dispatch, +Bool glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu); Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index d270cae59..010950e59 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -321,7 +321,11 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch = glamor_get_dispatch(glamor_priv); - glamor_set_alu(dispatch, gc->alu); + if (!glamor_set_alu(dispatch, gc->alu)) { + glamor_put_dispatch(glamor_priv); + goto fail; + } + glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index b6847a908..c5ecf85c5 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -75,7 +75,11 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); dispatch = glamor_get_dispatch(glamor_priv); - glamor_set_alu(dispatch, gc->alu); + if (!glamor_set_alu(dispatch, gc->alu)) { + glamor_put_dispatch(glamor_priv); + goto fail; + } + for (i = 0; i < n; i++) { n = REGION_NUM_RECTS(clip); diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index aa62d095e..be873ccc2 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -162,7 +162,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); dispatch = glamor_get_dispatch(glamor_priv); - glamor_set_alu(dispatch, alu); + if (!glamor_set_alu(dispatch, alu)) { + glamor_put_dispatch(glamor_priv); + goto fail; + } if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, From c6ce44d88134115b42edc76e1ee961b57bae86ff Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 6 Apr 2012 17:01:57 +0800 Subject: [PATCH 321/462] render: Enable more componentAlpha support. Actually only PictOpAtop,PictOpAtopReverse and PictOpXor can't be implemented by using single source blending. All the other can be easily support. Slightly change the code to support them. Consider those three Ops are not frequenly used in real application. We simply fallback them currently. PictOpAtop: s*mask*dst.a + (1 - s.a*mask)*dst PictOpAtopReverse: s*mask*(1 - dst.a) + dst *s.a*mask PictOpXor: s*mask*(1 - dst.a) + dst * (1 - s.a*mask) The two oprands in the above three ops are all reated to dst and the blend factors are not constant (0 or 1), it's hardly to convert it to single source blend. Now, the rendercheck is runing more smoothly. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 00a6e1ec9..9410adfee 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -461,11 +461,6 @@ glamor_set_composite_op(ScreenPtr screen, 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; - } if (dest_blend == GL_SRC_ALPHA) dest_blend = GL_SRC_COLOR; else if (dest_blend == GL_ONE_MINUS_SRC_ALPHA) @@ -954,15 +949,17 @@ glamor_composite_with_shader(CARD8 op, if (!mask->componentAlpha) { key.in = SHADER_IN_NORMAL; } else { - /* We only handle two CA modes. */ - if (op == PictOpAdd) + if (op == PictOpClear) + key.mask = SHADER_MASK_NONE; + else if (op == PictOpSrc || op == PictOpAdd + || op == PictOpIn || op == PictOpOut + || op == PictOpOverReverse) key.in = SHADER_IN_CA_SOURCE; - else if (op == PictOpOutReverse) { + else if (op == PictOpOutReverse || op == PictOpInReverse) { key.in = SHADER_IN_CA_ALPHA; } else { glamor_fallback - ("Unsupported component alpha op: %d\n", - op); + ("Unsupported component alpha op: %d\n", op); goto fail; } } @@ -2911,10 +2908,13 @@ _glamor_composite(CARD8 op, x_dest, y_dest, width, height); goto done; - } else if (op != PictOpAdd && op != PictOpOutReverse) { - glamor_fallback - ("glamor_composite(): component alpha\n"); - goto fail; + } else if (op == PictOpAtop + || op == PictOpAtopReverse + || op == PictOpXor + || op >= PictOpSaturate) { + glamor_fallback + ("glamor_composite(): component alpha op %x\n", op); + goto fail; } } if (!mask) { From 3b8b2c77fc4449c7b63fd2597f73562b33dc1722 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 6 Apr 2012 21:15:12 +0800 Subject: [PATCH 322/462] getimage: Enable getimage by default. Fixed one bug when calculate the coords, should consider the drawable's x and y. Now enable it by default. Most of the time, it should be more efficient than miGetImage. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index b1093e8e9..3aabaa5d3 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -45,14 +45,13 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, Bool ret = FALSE; int swap_rb; - goto fall_back; - - glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (format != ZPixmap) goto fall_back; + glamor_priv = glamor_get_screen_private(drawable->pScreen); pixmap = glamor_get_drawable_pixmap(drawable); + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + if (!glamor_set_planemask(pixmap, planeMask)) { glamor_fallback ("Failedto set planemask in glamor_solid.\n"); @@ -64,7 +63,6 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto fall_back; - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); if (glamor_get_tex_format_type_from_pixmap(pixmap, &tex_format, @@ -77,6 +75,9 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, goto fall_back; } + if (revert > REVERT_NORMAL) + goto fall_back; + glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); @@ -93,26 +94,29 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, } - int row_length = PixmapBytePad(w, drawable->depth); - row_length = (row_length * 8) / drawable->bitsPerPixel; dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + int row_length = PixmapBytePad(w, drawable->depth); + row_length = (row_length * 8) / drawable->bitsPerPixel; dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); } else { dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); } + x += drawable->x + x_off; + y += drawable->y + y_off; + if (glamor_priv->yInverted) - dispatch->glReadPixels(x + x_off, - y + y_off, + dispatch->glReadPixels(x, + y, w, h, tex_format, tex_type, d); else - dispatch->glReadPixels(x + x_off, - pixmap->drawable.height - 1 - (y + y_off), + dispatch->glReadPixels(x, + pixmap->drawable.height - 1 - y, w, h, tex_format, From 49e3b44aa813c98c05fcb10c19882e10d751580a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 6 Apr 2012 21:17:46 +0800 Subject: [PATCH 323/462] glamor_set_alu: Added GXclear support at glamor_solid. We don't need to issue the glamor_fallback at the glamor_set_alu routine, as the caller may support GXclear or other most frequent Ops. Leave it to the caller to determine fallback or not. Signed-off-by: Zhigang Gong --- glamor/glamor_fill.c | 9 +++++++-- glamor/glamor_pixmap.c | 5 +---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 53c750afb..4cee485e0 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -190,8 +190,13 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, alu)) { - glamor_put_dispatch(glamor_priv); - return FALSE; + if (alu == GXclear) + color[0] = color[1] = color[2] = color[3] = 0.0; + else { + glamor_fallback("unsupported alu %x\n", alu); + glamor_put_dispatch(glamor_priv); + return FALSE; + } } dispatch->glUseProgram(glamor_priv->solid_prog); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 35b2d56f1..066d9a779 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -204,10 +204,8 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) return FALSE; } #else - if (alu != GXcopy) { - glamor_fallback("unsupported alu %x\n", alu); + if (alu != GXcopy) return FALSE; - } #endif return TRUE; } @@ -872,7 +870,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, return temp_fbo; } - /** * Move a pixmap to CPU memory. * The input data is the pixmap's fbo. From 4dc6d4e84b4904540d7701cfc88a9c945464f833 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 6 Apr 2012 21:20:15 +0800 Subject: [PATCH 324/462] glyphblt/polyops: Use miFunctions by default. Calling to miFunctions give some opportunities to jump to accelerated path, so we switch to call miFunctions rather than fallback to fbFunctions directly. --- glamor/glamor_glyphblt.c | 30 +++++----------------- glamor/glamor_polyops.c | 54 +++------------------------------------- 2 files changed, 9 insertions(+), 75 deletions(-) diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c index 163099847..18ad536eb 100644 --- a/glamor/glamor_glyphblt.c +++ b/glamor/glamor_glyphblt.c @@ -38,17 +38,10 @@ _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) - goto fail; + return FALSE; - glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); - glamor_prepare_access_gc(pGC); - fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); - glamor_finish_access_gc(pGC); - glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); return TRUE; - fail: - return FALSE; } void @@ -74,17 +67,12 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, { glamor_screen_private *glamor_priv; - if (!fallback + if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) return FALSE; - glamor_priv = glamor_get_screen_private(pDrawable->pScreen); - glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); - glamor_prepare_access_gc(pGC); - fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); - glamor_finish_access_gc(pGC); - glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + miPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); return TRUE; } @@ -108,19 +96,13 @@ static Bool _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y, Bool fallback) { - if (!fallback + if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable) && glamor_ddx_fallback_check_gc(pGC)) return FALSE; - glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); - glamor_prepare_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); - glamor_prepare_access_gc(pGC); - fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); - glamor_finish_access_gc(pGC); - glamor_finish_access(&pBitmap->drawable, GLAMOR_ACCESS_RO); - glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); + miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y); return TRUE; } diff --git a/glamor/glamor_polyops.c b/glamor/glamor_polyops.c index 7320c1762..59301784d 100644 --- a/glamor/glamor_polyops.c +++ b/glamor/glamor_polyops.c @@ -37,11 +37,8 @@ _glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, && glamor_ddx_fallback_check_pixmap(pDrawable)) return FALSE; - glamor_prepare_access_gc(pGC); - glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); - fbPolyPoint(pDrawable, pGC, mode, npt, ppt); - glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); - glamor_finish_access_gc(pGC); + miPolyPoint(pDrawable, pGC, mode, npt, ppt); + return TRUE; } @@ -68,15 +65,7 @@ _glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, && glamor_ddx_fallback_check_pixmap(pDrawable)) return FALSE; - /* For lineWidth is not zero, fb calls to mi functions. */ - if (pGC->lineWidth == 0) { - glamor_prepare_access_gc(pGC); - glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); - fbPolySegment(pDrawable, pGC, nseg, pSeg); - glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); - glamor_finish_access_gc(pGC); - } else - fbPolySegment(pDrawable, pGC, nseg, pSeg); + miPolySegment(pDrawable, pGC, nseg, pSeg); return TRUE; } @@ -94,40 +83,3 @@ glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC, int nseg, { return _glamor_poly_segment(pDrawable, pGC, nseg, pSeg, FALSE); } - -static Bool -_glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr ppt, Bool fallback) -{ - if (!fallback - && glamor_ddx_fallback_check_gc(pGC) - && glamor_ddx_fallback_check_pixmap(pDrawable)) - return FALSE; - /* For lineWidth is not zero, fb calls to mi functions. */ - - if (pGC->lineWidth == 0) { - glamor_prepare_access_gc(pGC); - glamor_prepare_access(pDrawable, GLAMOR_ACCESS_RW); - fbPolyLine(pDrawable, pGC, mode, npt, ppt); - glamor_finish_access(pDrawable, GLAMOR_ACCESS_RW); - glamor_finish_access_gc(pGC); - } else - fbPolyLine(pDrawable, pGC, mode, npt, ppt); - - return TRUE; -} - -void -glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr ppt) -{ - _glamor_poly_line(pDrawable, pGC, mode, npt, ppt, TRUE); -} - -Bool -glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr ppt) -{ - return _glamor_poly_line(pDrawable, pGC, mode, npt, ppt, FALSE); -} - From 3dbdd40c6ce4203619f2a3492029a444bb9217af Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Apr 2012 10:00:57 +0800 Subject: [PATCH 325/462] glamor_color_convert: Let the caller to provide destination buffer. As we don't need to allocate new buffer when downloading pixmap to CPU, we change the prototype of the color converting function and let the caller to provide the buffer to hold the result. All the color conversion function supports store the result just at the same place of the source. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 50 ++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 066d9a779..de8774035 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -211,7 +211,7 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) } void * -_glamor_color_convert_a1_a8(void *src_bits, int w, int h, int stride, int revert) +_glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int stride, int revert) { void *bits; PictFormatShort dst_format, src_format; @@ -226,12 +226,9 @@ _glamor_color_convert_a1_a8(void *src_bits, int w, int h, int stride, int revert src_format = PICT_a8; } - bits = malloc(stride * h); - if (bits == NULL) - return NULL; dst_image = pixman_image_create_bits(dst_format, w, h, - bits, + dst_bits, stride); if (dst_image == NULL) { free(bits); @@ -255,7 +252,7 @@ _glamor_color_convert_a1_a8(void *src_bits, int w, int h, int stride, int revert pixman_image_unref(src_image); pixman_image_unref(dst_image); - return bits; + return dst_bits; } #define ADJUST_BITS(d, src_bits, dst_bits) (((dst_bits) == (src_bits)) ? (d) : \ @@ -298,16 +295,14 @@ _glamor_color_convert_a1_a8(void *src_bits, int w, int h, int stride, int revert } void * -_glamor_color_revert_x2b10g10r10(void *src_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) +_glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) { int x,y; unsigned int *words, *saved_words, *source_words; int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || swap_rb == SWAP_NONE_UPLOADING); - words = malloc(stride * h); source_words = src_bits; - if (words == NULL) - return NULL; + words = dst_bits; saved_words = words; for (y = 0; y < h; y++) @@ -337,16 +332,14 @@ _glamor_color_revert_x2b10g10r10(void *src_bits, int w, int h, int stride, int n } void * -_glamor_color_revert_x1b5g5r5(void *src_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) +_glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) { int x,y; unsigned short *words, *saved_words, *source_words; int swap = !(swap_rb == SWAP_NONE_DOWNLOADING || swap_rb == SWAP_NONE_UPLOADING); - words = malloc(stride * h); + words = dst_bits; source_words = src_bits; - if (words == NULL) - return NULL; saved_words = words; for (y = 0; y < h; y++) @@ -393,14 +386,14 @@ _glamor_color_revert_x1b5g5r5(void *src_bits, int w, int h, int stride, int no_a */ void * -glamor_color_convert_to_bits(void *src_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) +glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) { if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) { - return _glamor_color_convert_a1_a8(src_bits, w, h, stride, revert); + return _glamor_color_convert_a1_a8(src_bits, dst_bits, w, h, stride, revert); } else if (revert == REVERT_DOWNLOADING_2_10_10_10 || revert == REVERT_UPLOADING_2_10_10_10) { - return _glamor_color_revert_x2b10g10r10(src_bits, w, h, stride, no_alpha, revert, swap_rb); + return _glamor_color_revert_x2b10g10r10(src_bits, dst_bits, w, h, stride, no_alpha, revert, swap_rb); } else if (revert == REVERT_DOWNLOADING_1_5_5_5 || revert == REVERT_UPLOADING_1_5_5_5) { - return _glamor_color_revert_x1b5g5r5(src_bits, w, h, stride, no_alpha, revert, swap_rb); + return _glamor_color_revert_x1b5g5r5(src_bits, dst_bits, w, h, stride, no_alpha, revert, swap_rb); } else ErrorF("convert a non-supported mode %x.\n", revert); @@ -501,7 +494,12 @@ glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum typ if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 && revert > REVERT_NORMAL) { - bits = glamor_color_convert_to_bits(bits, pixmap->drawable.width, + /* XXX if we are restoring the pixmap, then we may not need to allocate + * new buffer */ + void *converted_bits = malloc(pixmap->drawable.height * pixmap->devKind); + if (converted_bits == NULL) + return FALSE; + bits = glamor_color_convert_to_bits(bits, converted_bits, pixmap->drawable.width, pixmap->drawable.height, pixmap->devKind, no_alpha, revert, swap_rb); @@ -1041,7 +1039,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (need_post_conversion) { /* As OpenGL desktop version never enters here. * Don't need to consider if the pbo is valid.*/ - char *new_data; int stride; assert(pixmap_priv->fbo->pbo_valid == 0); @@ -1050,15 +1047,10 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) stride = (((pixmap->drawable.width * 8 + 7) / 8) + 3) & ~3; else stride = pixmap->devKind; - new_data = glamor_color_convert_to_bits(data, pixmap->drawable.width, - pixmap->drawable.height, - stride, no_alpha, - revert, swap_rb); - free(data); - if (new_data == NULL) { - return FALSE; - } - data = new_data; + glamor_color_convert_to_bits(data, data, pixmap->drawable.width, + pixmap->drawable.height, + stride, no_alpha, + revert, swap_rb); } done: From d96226ac6f34aa61fc00ad15ef58c1ed1253160e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Apr 2012 15:57:05 +0800 Subject: [PATCH 326/462] glamor_es2_pixmap_read_prepare: Just prepare the required region. Don't need to prepare the whole source pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 19 ++++++++++--------- glamor/glamor_getspans.c | 2 +- glamor/glamor_pixmap.c | 14 +++++++------- glamor/glamor_priv.h | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 3aabaa5d3..15ee89dcf 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -81,20 +81,25 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_validate_pixmap(pixmap); + x += drawable->x + x_off; + y += drawable->y + y_off; + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 && ( swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { - /* XXX prepare whole pixmap is not efficient. */ temp_fbo = - glamor_es2_pixmap_read_prepare(pixmap, tex_format, + glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h, tex_format, tex_type, no_alpha, revert, swap_rb); - if (temp_fbo == NULL) + if (temp_fbo == NULL) { + x -= (drawable->x + x_off); + y -= (drawable->y + y_off); goto fall_back; - + } + x = 0; + y = 0; } - dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { int row_length = PixmapBytePad(w, drawable->depth); @@ -105,9 +110,6 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); } - x += drawable->x + x_off; - y += drawable->y + y_off; - if (glamor_priv->yInverted) dispatch->glReadPixels(x, y, @@ -124,7 +126,6 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, glamor_put_dispatch(glamor_priv); if (temp_fbo) glamor_destroy_fbo(temp_fbo); - ret = TRUE; fall_back: diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 8341df42e..bd6a5ec19 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -73,7 +73,7 @@ _glamor_get_spans(DrawablePtr drawable, /* XXX prepare whole pixmap is not efficient. */ temp_fbo = - glamor_es2_pixmap_read_prepare(pixmap, format, + glamor_es2_pixmap_read_prepare(pixmap, 0, 0, pixmap->drawable.width, pixmap->drawable.height, format, type, no_alpha, revert, swap_rb); if (temp_fbo == NULL) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index de8774035..bab91af84 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -788,7 +788,7 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap) * */ glamor_pixmap_fbo * -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, +glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLenum format, GLenum type, int no_alpha, int revert, int swap_rb) { @@ -806,8 +806,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, glamor_priv = glamor_get_screen_private(screen); source_priv = glamor_get_pixmap_private(source); temp_fbo = glamor_create_fbo(glamor_priv, - source->drawable.width, - source->drawable.height, + w, h, format, 0); if (temp_fbo == NULL) @@ -820,7 +819,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, glamor_set_normalize_vcoords(temp_xscale, temp_yscale, 0, 0, - source->drawable.width, source->drawable.height, + w, h, glamor_priv->yInverted, vertices); @@ -832,8 +831,8 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale); glamor_set_normalize_tcoords(source_xscale, source_yscale, - 0, 0, - source->drawable.width, source->drawable.height, + x, y, + x + w, y + h, glamor_priv->yInverted, texcoords); @@ -928,7 +927,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 && !need_post_conversion && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { - if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, format, + if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, 0, 0, + pixmap->drawable.width, pixmap->drawable.height, format, type, no_alpha, revert, swap_rb))) return FALSE; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index bea4f662a..3e13ef8e2 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -465,7 +465,7 @@ void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv); glamor_pixmap_fbo * -glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format, +glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLenum format, GLenum type, int no_alpha, int revert, int swap_rb); Bool glamor_set_alu(struct glamor_gl_dispatch *dispatch, From d9dfc3d795b7e567d53cfeed61126164be36e233 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Apr 2012 16:39:42 +0800 Subject: [PATCH 327/462] glamor_download_sub_pixmap_to_cpu: New function to download subregion. Prepare to optimize the fallback path. We choose the important rendering pathes to optimzie it by using shader. For other pathes, we have to fallback. We may continue to optimize more pathes in the future, but now we have to face those fallbacks. The original fallback is very slow and will download/upload the whole pixmap. From this commit, I will refine it to just download/upload needed part. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 345 +++++++++++++++++++++++------------------ 1 file changed, 196 insertions(+), 149 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index bab91af84..02b311a97 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -867,6 +867,175 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe return temp_fbo; } +/* + * Download a sub region of pixmap to a specified memory region. + * The pixmap must have a valid FBO, otherwise return a NULL. + * */ + +void * +glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, + int stride, void *bits, int pbo, glamor_access_t access) +{ + glamor_pixmap_private *pixmap_priv; + unsigned int row_length; + GLenum format, type, gl_access, gl_usage; + int no_alpha, revert, swap_rb; + void *data, *read; + ScreenPtr screen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + glamor_gl_dispatch *dispatch; + glamor_pixmap_fbo *temp_fbo = NULL; + int need_post_conversion = 0; + int need_free_data = 0; + + data = bits; + screen = pixmap->drawable.pScreen; + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return NULL; + + switch (access) { + case GLAMOR_ACCESS_RO: + gl_access = GL_READ_ONLY; + gl_usage = GL_STREAM_READ; + break; + case GLAMOR_ACCESS_WO: + return bits; + case GLAMOR_ACCESS_RW: + gl_access = GL_READ_WRITE; + gl_usage = GL_DYNAMIC_DRAW; + break; + default: + ErrorF("Glamor: Invalid access code. %d\n", access); + assert(0); + } + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &no_alpha, + &revert, + &swap_rb, 0)) { + ErrorF("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + assert(0); // Should never happen. + return NULL; + } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + /* XXX we may don't need to validate it on GPU here, + * we can just validate it on CPU. */ + glamor_validate_pixmap(pixmap); + + need_post_conversion = (revert > REVERT_NORMAL); + if (need_post_conversion) { + if (pixmap->drawable.depth == 1) { + stride = (((w * 8 + 7) / 8) + 3) & ~3; + data = malloc(stride * h); + if (data == NULL) + return NULL; + need_free_data = 1; + } + } + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && !need_post_conversion + && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { + if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h, + format, type, no_alpha, + revert, swap_rb))) + return NULL; + x = 0; + y = 0; + } + + + dispatch = glamor_get_dispatch(glamor_priv); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); + dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); + } else { + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); + } + if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { + + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == + GLAMOR_GL_DESKTOP); + dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); + } + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) { + assert(pbo > 0); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, + stride * + h, + NULL, gl_usage); + } + + dispatch->glReadPixels(x, y, w, h, format, type, data); + + if (!glamor_priv->yInverted) { + assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); + dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 0); + } + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) { + bits = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, + gl_access); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + } + } else { + int temp_pbo; + int yy; + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glGenBuffers(1, &temp_pbo); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, + temp_pbo); + dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, + stride * + pixmap->drawable.height, + NULL, GL_STREAM_READ); + dispatch->glReadPixels(0, 0, row_length, + pixmap->drawable.height, + format, type, 0); + read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, + GL_READ_ONLY); + for (yy = 0; yy < pixmap->drawable.height; yy++) + memcpy(data + yy * stride, + read + (pixmap->drawable.height - + yy - 1) * stride, stride); + dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + dispatch->glDeleteBuffers(1, &temp_pbo); + } + + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); + glamor_put_dispatch(glamor_priv); + + if (need_post_conversion) { + /* As OpenGL desktop version never enters here. + * Don't need to consider if the pbo is valid.*/ + bits = glamor_color_convert_to_bits(data, bits, + w, h, + stride, no_alpha, + revert, swap_rb); + } + + done: + + if (temp_fbo != NULL) + glamor_destroy_fbo(temp_fbo); + if (need_free_data) + free(data); + + return bits; +} + + /** * Move a pixmap to CPU memory. * The input data is the pixmap's fbo. @@ -884,28 +1053,16 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) unsigned int stride, row_length, y; GLenum format, type, gl_access, gl_usage; int no_alpha, revert, swap_rb; - uint8_t *data = NULL, *read; + void *data = NULL, *dst; ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; - glamor_pixmap_fbo *temp_fbo = NULL; - int need_post_conversion = 0; + int pbo = 0; screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &revert, - &swap_rb, 0)) { - ErrorF("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - assert(0); // Should never happen. - return FALSE; - } glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DOWNLOAD, "Downloading pixmap %p %dx%d depth%d\n", @@ -916,150 +1073,40 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) stride = pixmap->devKind; - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - /* XXX we may don't need to validate it on GPU here, - * we can just validate it on CPU. */ - glamor_validate_pixmap(pixmap); - - - need_post_conversion = (revert > REVERT_NORMAL); - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && !need_post_conversion - && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { - if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, 0, 0, - pixmap->drawable.width, pixmap->drawable.height, format, - type, no_alpha, - revert, swap_rb))) - return FALSE; - } - switch (access) { - case GLAMOR_ACCESS_RO: - gl_access = GL_READ_ONLY; - gl_usage = GL_STREAM_READ; - break; - case GLAMOR_ACCESS_WO: + if (access == GLAMOR_ACCESS_WO + || glamor_priv->gl_flavor == GLAMOR_GL_ES2 + || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)) { data = malloc(stride * pixmap->drawable.height); - goto done; - break; - case GLAMOR_ACCESS_RW: - gl_access = GL_READ_WRITE; - gl_usage = GL_DYNAMIC_DRAW; - break; - default: - ErrorF("Glamor: Invalid access code. %d\n", access); - assert(0); - } - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - data = malloc(stride * pixmap->drawable.height); - } - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - - dispatch = glamor_get_dispatch(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); } else { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); - // dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, 0); - } - if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { - - if (!glamor_priv->yInverted) { - assert(glamor_priv->gl_flavor == - GLAMOR_GL_DESKTOP); - dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1); - } - - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (pixmap_priv->fbo->pbo == 0) - dispatch->glGenBuffers(1, - &pixmap_priv->fbo->pbo); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->fbo->pbo); - dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, - stride * - pixmap->drawable.height, - NULL, gl_usage); - dispatch->glReadPixels(0, 0, row_length, - pixmap->drawable.height, - format, type, 0); - data = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, - gl_access); - pixmap_priv->fbo->pbo_valid = TRUE; - - if (!glamor_priv->yInverted) { - assert(glamor_priv->gl_flavor == - GLAMOR_GL_DESKTOP); - dispatch->glPixelStorei - (GL_PACK_INVERT_MESA, 0); - } - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - } else { - dispatch->glReadPixels(0, 0, - pixmap->drawable.width, - pixmap->drawable.height, - format, type, data); - } - } else { - data = malloc(stride * pixmap->drawable.height); - assert(data); - if (access != GLAMOR_ACCESS_WO) { - if (pixmap_priv->fbo->pbo == 0) - dispatch->glGenBuffers(1, - &pixmap_priv->fbo->pbo); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, - pixmap_priv->fbo->pbo); - dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, - stride * - pixmap->drawable.height, - NULL, GL_STREAM_READ); - dispatch->glReadPixels(0, 0, row_length, - pixmap->drawable.height, - format, type, 0); - read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, - GL_READ_ONLY); - - for (y = 0; y < pixmap->drawable.height; y++) - memcpy(data + y * stride, - read + (pixmap->drawable.height - - y - 1) * stride, stride); - dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - pixmap_priv->fbo->pbo_valid = FALSE; - dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); - pixmap_priv->fbo->pbo = 0; - } + dispatch = glamor_get_dispatch(glamor_priv); + if (pixmap_priv->fbo->pbo == 0) + dispatch->glGenBuffers(1, + &pixmap_priv->fbo->pbo); + glamor_put_dispatch(glamor_priv); + pbo = pixmap_priv->fbo->pbo; + glamor_put_dispatch(glamor_priv); } - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0); - glamor_put_dispatch(glamor_priv); + dst = glamor_download_sub_pixmap_to_cpu(pixmap, 0, 0, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->devKind, + data, pbo, access); - if (need_post_conversion) { - /* As OpenGL desktop version never enters here. - * Don't need to consider if the pbo is valid.*/ - int stride; - assert(pixmap_priv->fbo->pbo_valid == 0); - - /* Only A1 <--> A8 conversion need to adjust the stride value. */ - if (pixmap->drawable.depth == 1) - stride = (((pixmap->drawable.width * 8 + 7) / 8) + 3) & ~3; - else - stride = pixmap->devKind; - glamor_color_convert_to_bits(data, data, pixmap->drawable.width, - pixmap->drawable.height, - stride, no_alpha, - revert, swap_rb); + if (!dst) { + if (data) + free(data); + return FALSE; } + if (pbo != 0) + pixmap_priv->fbo->pbo_valid = 1; + + pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; + done: - pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; - pixmap->devPrivate.ptr = data; - - if (temp_fbo != NULL) - glamor_destroy_fbo(temp_fbo); + pixmap->devPrivate.ptr = dst; return TRUE; } From cea0fe3e1f49fc8d86f0cc653c8089f1ea2c9f1f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Apr 2012 20:16:07 +0800 Subject: [PATCH 328/462] fallback_optimize: Prepare for downloading/uploading subregion. Introduced two function glamor_get_sub_pixmap/glamor_put_sub_pixmap, can easily used to get and put sub region of a big textured pixmap. And it can use pbo if possible. To support download a big textured pixmap's sub region to another pixmap's pbo, we introduce a new type of pixmap GLAMOR_MEMORY_MAP. This type of pixmap has a valid devPrivate.ptr pointer, and that pointer points to a pbo mapped address. Now, we are ready to refine those glamor_prepare_access/glamor_finish_access pairs. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 3 + glamor/glamor.h | 1 + glamor/glamor_fbo.c | 134 +++++++++++++++++++++++++--- glamor/glamor_pixmap.c | 197 +++++++++++++++++++++++++++-------------- glamor/glamor_priv.h | 25 ++++-- 5 files changed, 272 insertions(+), 88 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 8fc3b0534..9b1d425ea 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -155,6 +155,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, } glamor_set_pixmap_private(pixmap, pixmap_priv); + if (usage == GLAMOR_CREATE_PIXMAP_MAP) + type = GLAMOR_MEMORY_MAP; + pixmap_priv->container = pixmap; pixmap_priv->glamor_priv = glamor_priv; pixmap_priv->type = type; diff --git a/glamor/glamor.h b/glamor/glamor.h index 4a4e9bdcb..c608ed855 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -51,6 +51,7 @@ */ typedef enum glamor_pixmap_type { GLAMOR_MEMORY, + GLAMOR_MEMORY_MAP, GLAMOR_TEXTURE_DRM, GLAMOR_SEPARATE_TEXTURE, GLAMOR_DRM_ONLY, diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index b15450a6d..e9612bd7f 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -132,7 +132,6 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo) free(fbo); } - static void glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) { @@ -165,6 +164,55 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) #endif } +static void +glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) +{ + glamor_gl_dispatch *dispatch; + int status; + + dispatch = glamor_get_dispatch(fbo->glamor_priv); + + if (fbo->fb == 0) + dispatch->glGenFramebuffers(1, &fbo->fb); + assert(fbo->tex != 0); + dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); + dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, fbo->tex, + 0); + status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + const char *str; + switch (status) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + str = "incomplete attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + str = "incomplete/missing attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + str = "incomplete draw buffer"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + str = "incomplete read buffer"; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + str = "unsupported"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + str = "incomplete multiple"; + break; + default: + str = "unknown error"; + break; + } + + FatalError("destination is framebuffer incomplete: %s [%#x]\n", + str, status); + } + glamor_put_dispatch(fbo->glamor_priv); +} + glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format, GLint tex, int flag) @@ -183,9 +231,18 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, fbo->format = format; fbo->glamor_priv = glamor_priv; + if (flag == GLAMOR_CREATE_PIXMAP_MAP) { + glamor_gl_dispatch *dispatch; + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glGenBuffers(1, &fbo->pbo); + glamor_put_dispatch(glamor_priv); + goto done; + } + if (flag != GLAMOR_CREATE_FBO_NO_FBO) glamor_pixmap_ensure_fb(fbo); +done: return fbo; } @@ -331,6 +388,28 @@ glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) glamor_pixmap_fbo_cache_put(tex_obj); } +int +_glamor_create_tex(glamor_screen_private *glamor_priv, + int w, int h, GLenum format) +{ + glamor_gl_dispatch *dispatch; + int tex; + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glGenTextures(1, &tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, + GL_UNSIGNED_BYTE, NULL); + glamor_put_dispatch(glamor_priv); + return tex; +} + + + glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, @@ -339,7 +418,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, { glamor_gl_dispatch *dispatch; glamor_pixmap_fbo *fbo; - GLint tex; + GLint tex = 0; int cache_flag; if (!glamor_check_fbo_size(glamor_priv, w, h)) @@ -348,6 +427,9 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, if (flag == GLAMOR_CREATE_FBO_NO_FBO) goto new_fbo; + if (flag == GLAMOR_CREATE_PIXMAP_MAP) + goto no_tex; + if (flag == GLAMOR_CREATE_PIXMAP_FIXUP) cache_flag = GLAMOR_CACHE_EXACT_SIZE; else @@ -358,18 +440,9 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, if (fbo) return fbo; new_fbo: - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glGenTextures(1, &tex); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, - GL_UNSIGNED_BYTE, NULL); - + tex = _glamor_create_tex(glamor_priv, w, h, format); +no_tex: fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag); - glamor_put_dispatch(glamor_priv); return fbo; } @@ -424,12 +497,47 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) /* XXX For the Xephyr only, may be broken now.*/ pixmap_priv->gl_tex = 0; } + case GLAMOR_MEMORY_MAP: pixmap->devPrivate.ptr = NULL; break; default: break; } } + + +Bool +glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) +{ + glamor_screen_private *glamor_priv; + glamor_pixmap_private *pixmap_priv; + glamor_pixmap_fbo *fbo; + + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) { + + fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, + format, + flag); + if (fbo == NULL) + return FALSE; + + glamor_pixmap_attach_fbo(pixmap, fbo); + } else { + /* We do have a fbo, but it may lack of fb or tex. */ + if (pixmap_priv->fbo->tex) + pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, format); + + if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0) + glamor_pixmap_ensure_fb(pixmap_priv->fbo); + } + + pixmap_priv = glamor_get_pixmap_private(pixmap); + return TRUE; +} /* * XXX how to handle those pending OPs. * By default, pending OP is disabled. Maybe we will give up the pending diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 02b311a97..82002d7d8 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -622,54 +622,6 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, pixmap->devPrivate.ptr); } -void -glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) -{ - glamor_gl_dispatch *dispatch; - int status; - - dispatch = glamor_get_dispatch(fbo->glamor_priv); - - if (fbo->fb == 0) - dispatch->glGenFramebuffers(1, &fbo->fb); - assert(fbo->tex != 0); - dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); - dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, fbo->tex, - 0); - status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - const char *str; - switch (status) { - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - str = "incomplete attachment"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - str = "incomplete/missing attachment"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - str = "incomplete draw buffer"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - str = "incomplete read buffer"; - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - str = "unsupported"; - break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - str = "incomplete multiple"; - break; - default: - str = "unknown error"; - break; - } - - FatalError("destination is framebuffer incomplete: %s [%#x]\n", - str, status); - } - glamor_put_dispatch(fbo->glamor_priv); -} /* * Prepare to upload a pixmap to texture memory. @@ -681,7 +633,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) static int glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int revert, int swap_rb) { - int flag; + int flag = 0; glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; glamor_pixmap_fbo *fbo; @@ -696,36 +648,38 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int || !glamor_priv->yInverted)) { /* We don't need a fbo, a simple texture uploading should work. */ - if (pixmap_priv && pixmap_priv->fbo) - return 0; flag = GLAMOR_CREATE_FBO_NO_FBO; - } else { - - if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - return 0; - flag = 0; } + if ((flag == 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->tex) + || (flag != 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb)) + return 0; + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) gl_iformat_for_depth(pixmap->drawable.depth, &iformat); else iformat = format; + if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) { - fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, - iformat, - flag); - if (fbo == NULL) { - glamor_fallback - ("upload failed, depth %d x %d @depth %d \n", - pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth); - return -1; + fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, + pixmap->drawable.height, + iformat, + flag); + if (fbo == NULL) { + glamor_fallback + ("upload failed, depth %d x %d @depth %d \n", + pixmap->drawable.width, pixmap->drawable.height, + pixmap->drawable.depth); + return -1; + } + + glamor_pixmap_attach_fbo(pixmap, fbo); + } else { + /* We do have a fbo, but it may lack of fb or tex. */ + glamor_pixmap_ensure_fbo(pixmap, iformat, flag); } - glamor_pixmap_attach_fbo(pixmap, fbo); - return 0; } @@ -1173,3 +1127,110 @@ fail: return ret; } + +/* + * We may use this function to reduce a large pixmap to a small sub + * pixmap. Two scenarios currently: + * 1. When fallback a large textured pixmap to CPU but we do need to + * do rendering within a small sub region, then we can just get a + * sub region. + * + * 2. When uploading a large pixmap to texture but we only need to + * use part of the source/mask picture. As glTexImage2D will be more + * efficient to upload a contingent region rather than a sub block + * in a large buffer. We use this function to gather the sub region + * to a contingent sub pixmap. + * + * The sub-pixmap must have the same format as the source pixmap. + * + * */ +PixmapPtr +glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access) +{ + glamor_screen_private *glamor_priv; + PixmapPtr sub_pixmap; + glamor_pixmap_private *sub_pixmap_priv, *pixmap_priv; + void *data; + int pbo; + int flag; + + if (access == GLAMOR_ACCESS_WO) { + sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, + pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); + ErrorF("WO\n"); + return sub_pixmap; + } + + glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return NULL; + + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + flag = GLAMOR_CREATE_PIXMAP_CPU; + else + flag = GLAMOR_CREATE_PIXMAP_MAP; + + sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, + pixmap->drawable.depth, flag); + + if (sub_pixmap == NULL) + return NULL; + + sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); + pbo = sub_pixmap_priv ? (sub_pixmap_priv->fbo ? sub_pixmap_priv->fbo->pbo : 0): 0; + + if (pbo) + data = NULL; + else { + data = sub_pixmap->devPrivate.ptr; + assert(flag != GLAMOR_CREATE_PIXMAP_MAP); + } + data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind, + data, pbo, access); + if (pbo) { + assert(sub_pixmap->devPrivate.ptr == NULL); + sub_pixmap->devPrivate.ptr = data; + sub_pixmap_priv->fbo->pbo_valid = 1; + } +#if 0 + struct pixman_box16 box; + PixmapPtr new_sub_pixmap; + int dx, dy; + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + + dx = x; + dy = y; + + new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, + pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); + glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap, NULL, &box, 1, dx, dy, 0, 0, 0, NULL); + glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1); +#endif + + return sub_pixmap; +} + +PixmapPtr +glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access) +{ + struct pixman_box16 box; + int dx, dy; + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + + dx = -(x); + dy = -(y); + + glamor_copy_n_to_n(&sub_pixmap->drawable, + &pixmap->drawable, + NULL, &box, 1, dx, dy, + 0, 0, 0, NULL); + glamor_destroy_pixmap(sub_pixmap); +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3e13ef8e2..8a6beeea9 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -145,8 +145,8 @@ enum glamor_gl_flavor { #define GLAMOR_CREATE_PIXMAP_CPU 0x100 #define GLAMOR_CREATE_PIXMAP_FIXUP 0x101 - #define GLAMOR_CREATE_FBO_NO_FBO 0x103 +#define GLAMOR_CREATE_PIXMAP_MAP 0x104 #define GLAMOR_CREATE_TEXTURE_EXACT_SIZE 0x104 @@ -615,15 +615,16 @@ Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, * must be 1. **/ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap); + /** - * Ensure to have a fbo has a valid/complete glfbo. + * According to the flag, + * if the flag is GLAMOR_CREATE_FBO_NO_FBO then just ensure + * the fbo has a valid texture. Otherwise, it will ensure + * the fbo has valid texture and attach to a valid fb. * If the fbo already has a valid glfbo then do nothing. - * Otherwise, it will generate a new glfbo, and bind - * the fbo's texture to the glfbo. - * The fbo must has a valid texture before call this - * API, othersie, it will trigger a assert. */ -void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo); +Bool +glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag); /** * Upload a pixmap to gl texture. Used by dynamic pixmap @@ -633,6 +634,16 @@ void glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo); enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap); + +PixmapPtr +glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, + int w, int h, glamor_access_t access); + +PixmapPtr +glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, + int w, int h, glamor_access_t access); + + /** * Upload a picture to gl texture. Similar to the * glamor_upload_pixmap_to_texture. Used in rendering. From 1f657f72cacaa1170e7e55f4b5149c69492db6a5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 9 Apr 2012 20:20:45 +0800 Subject: [PATCH 329/462] glamor_polyfillrect: Optimize fallback path. Download/upload required region only. Signed-off-by: Zhigang Gong --- glamor/glamor_fill.c | 40 ++++++++++++++++++++++++++++++++++++ glamor/glamor_polyfillrect.c | 4 ---- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 4cee485e0..3c171d458 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -33,6 +33,10 @@ glamor_fill(DrawablePtr drawable, { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); int off_x, off_y; + PixmapPtr sub_pixmap = NULL; + glamor_access_t sub_pixmap_access; + DrawablePtr saved_drawable = NULL; + int saved_x, saved_y; glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y); @@ -82,7 +86,26 @@ glamor_fill(DrawablePtr drawable, && glamor_ddx_fallback_check_gc(gc)) return FALSE; } + /* Is it possible to set the access as WO? */ + sub_pixmap_access = GLAMOR_ACCESS_RW; + + sub_pixmap = glamor_get_sub_pixmap(dst_pixmap, x + off_x, + y + off_y, width, height, + sub_pixmap_access); + + if (sub_pixmap != NULL) { + if (gc->fillStyle != FillSolid) { + gc->patOrg.x += (drawable->x - x); + gc->patOrg.y += (drawable->y - y); + } + saved_drawable = drawable; + drawable = &sub_pixmap->drawable; + saved_x = x; + saved_y = y; + x = 0; + y = 0; + } if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { fbFill(drawable, gc, x, y, width, height); @@ -90,6 +113,23 @@ glamor_fill(DrawablePtr drawable, } glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } + + if (sub_pixmap != NULL) { + struct pixman_box16 box; + int dx, dy; + if (gc->fillStyle != FillSolid) { + gc->patOrg.x -= (saved_drawable->x - saved_x); + gc->patOrg.y -= (saved_drawable->y - saved_y); + } + + x = saved_x; + y = saved_y; + + glamor_put_sub_pixmap(sub_pixmap, dst_pixmap, + x + off_x, y + off_y, + width, height, sub_pixmap_access); + } + return TRUE; } diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 61e707f59..18f4fedf3 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -47,10 +47,6 @@ _glamor_poly_fill_rect(DrawablePtr drawable, glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) { - goto fail; - } - xorg = drawable->x; yorg = drawable->y; From 3a91f169122ea0556f628f11fb473b0feed7e44b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 10 Apr 2012 10:19:30 +0800 Subject: [PATCH 330/462] glamor_polyfillrect: Fixed a potential bug if fallback at glamor_fill. We should advance the prect after we successfully excuted the glamor_fill. And if failed, we need to add the failed 1 box back to nbox. Although, this bug will never happen currently, as glamor_fill will never fallback. Signed-off-by: Zhigang Gong --- glamor/glamor_polyfillrect.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 18f4fedf3..bbe10a1b1 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -44,6 +44,7 @@ _glamor_poly_fill_rect(DrawablePtr drawable, RegionPtr pClip = fbGetCompositeClip(gc); Bool ret = FALSE; glamor_screen_private *glamor_priv; + xRectangle *saved_prect = prect; glamor_priv = glamor_get_screen_private(drawable->pScreen); @@ -55,7 +56,6 @@ _glamor_poly_fill_rect(DrawablePtr drawable, fullY1 = prect->y + yorg; fullX2 = fullX1 + (int) prect->width; fullY2 = fullY1 + (int) prect->height; - prect++; n = REGION_NUM_RECTS(pClip); pbox = REGION_RECTS(pClip); @@ -78,14 +78,17 @@ _glamor_poly_fill_rect(DrawablePtr drawable, y1 = pbox->y1; if (pbox->y2 < y2) y2 = pbox->y2; - pbox++; + pbox++; if (x1 >= x2 || y1 >= y2) continue; if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, - y2 - y1, fallback)) + y2 - y1, fallback)) { + nrect++; goto fail; + } } + prect++; } ret = TRUE; goto done; From 3061f348ca2f05d88ca2391e1ad81ce8216d69f2 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 10 Apr 2012 10:40:17 +0800 Subject: [PATCH 331/462] glamor_getimage: Use glamor_download_sub_pixmap_to_cpu to get image. Reduce the duplicate logic. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 68 +++++----------------------------------- glamor/glamor_priv.h | 5 +++ 2 files changed, 13 insertions(+), 60 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 15ee89dcf..ddf057f59 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -44,6 +44,8 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, glamor_gl_dispatch * dispatch; Bool ret = FALSE; int swap_rb; + int stride; + void *data; if (format != ZPixmap) goto fall_back; @@ -63,71 +65,17 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto fall_back; - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &tex_format, - &tex_type, - &no_alpha, - &revert, - &swap_rb, - 0)) { - glamor_fallback("unknown depth. %d \n", drawable->depth); - goto fall_back; - } - - if (revert > REVERT_NORMAL) - goto fall_back; - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); + stride = PixmapBytePad(w, drawable->depth); x += drawable->x + x_off; y += drawable->y + y_off; - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && ( swap_rb != SWAP_NONE_DOWNLOADING - || revert != REVERT_NONE)) { - temp_fbo = - glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h, tex_format, - tex_type, no_alpha, - revert, swap_rb); - if (temp_fbo == NULL) { - x -= (drawable->x + x_off); - y -= (drawable->y + y_off); - goto fall_back; - } - x = 0; - y = 0; + data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, stride, + d, 0, GLAMOR_ACCESS_RO); + if (data != NULL) { + ret = TRUE; + assert(data == d); } - - dispatch = glamor_get_dispatch(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - int row_length = PixmapBytePad(w, drawable->depth); - row_length = (row_length * 8) / drawable->bitsPerPixel; - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); - } else { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); - } - - if (glamor_priv->yInverted) - dispatch->glReadPixels(x, - y, - w, h, - tex_format, - tex_type, d); - else - dispatch->glReadPixels(x, - pixmap->drawable.height - 1 - y, - w, - h, - tex_format, - tex_type, d); - glamor_put_dispatch(glamor_priv); - if (temp_fbo) - glamor_destroy_fbo(temp_fbo); - ret = TRUE; - fall_back: if (ret == FALSE) miGetImage(drawable, x, y, w, h, format, planeMask, d); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 8a6beeea9..cfa46e537 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -605,6 +605,11 @@ void glamor_pixmap_fini(ScreenPtr screen); Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access); +void * +glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, + int stride, void *bits, int pbo, glamor_access_t access); + + /** * Restore a pixmap's data which is downloaded by * glamor_download_pixmap_to_cpu to its original From b0e91f0f5a3a4f74800b89ed4003d300ae138151 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 10 Apr 2012 20:50:14 +0800 Subject: [PATCH 332/462] glamor_pixmap_upload_texture: Support to upload a sub region of data. Just as the downloading side, we can upload an sub region data to a pixmap's specified region. The data could be in memory or in a pbo buffer. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 191 +++++++++++++++++---------------------- glamor/glamor_priv.h | 4 + glamor/glamor_putimage.c | 36 ++------ 3 files changed, 96 insertions(+), 135 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 82002d7d8..77fd033d9 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -406,66 +406,60 @@ glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, int s **/ int in_restore = 0; static void -__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, GLuint tex, int sub, - void *bits) +__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, int *tex, + GLenum format, + GLenum type, + int x, int y, int w, int h, + void *bits, int pbo) { - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; - unsigned int stride, row_length; - GLenum iformat; - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) - iformat = format; - else - gl_iformat_for_depth(pixmap->drawable.depth, &iformat); - - stride = pixmap->devKind; - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); + if (*tex == 0) { + int iformat; + dispatch->glGenTextures(1, tex); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + gl_iformat_for_depth(pixmap->drawable.depth, &iformat); + else + iformat = format; + + dispatch->glBindTexture(GL_TEXTURE_2D, *tex); + dispatch->glTexImage2D(GL_TEXTURE_2D, + 0, + iformat, + w, h, 0, format, type, + bits); + } else + dispatch->glBindTexture(GL_TEXTURE_2D, *tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - } else { - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, - pixmap_priv->fbo->pbo); + pbo); - if (sub) - dispatch->glTexSubImage2D(GL_TEXTURE_2D, - 0,0,0, - pixmap->drawable.width, - pixmap->drawable.height, format, type, - bits); - else - dispatch->glTexImage2D(GL_TEXTURE_2D, - 0, - iformat, - pixmap->drawable.width, - pixmap->drawable.height, 0, format, type, - bits); + dispatch->glTexSubImage2D(GL_TEXTURE_2D, + 0, x, y, w, h, + format, type, + bits); if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glamor_put_dispatch(glamor_priv); } -Bool -glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type, - int no_alpha, int revert, int swap_rb, void *bits) +static Bool +_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type, + int no_alpha, int revert, + int swap_rb, int x, int y, int w, int h, + int stride, void* bits, int pbo) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); @@ -483,7 +477,7 @@ glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum typ }; float *ptexcoords; float dst_xscale, dst_yscale; - GLuint tex; + GLuint tex = 0; int need_flip; int need_free_bits = 0; @@ -496,12 +490,11 @@ glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum typ && revert > REVERT_NORMAL) { /* XXX if we are restoring the pixmap, then we may not need to allocate * new buffer */ - void *converted_bits = malloc(pixmap->drawable.height * pixmap->devKind); + void *converted_bits = malloc(h * stride); if (converted_bits == NULL) return FALSE; - bits = glamor_color_convert_to_bits(bits, converted_bits, pixmap->drawable.width, - pixmap->drawable.height, - pixmap->devKind, + bits = glamor_color_convert_to_bits(bits, converted_bits, w, h, + stride, no_alpha, revert, swap_rb); if (bits == NULL) { ErrorF("Failed to convert pixmap no_alpha %d, revert mode %d, swap mode %d\n", swap_rb); @@ -520,9 +513,11 @@ ready_to_upload: && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip) { - __glamor_upload_pixmap_to_texture(pixmap, format, type, - pixmap_priv->fbo->tex, 1, - bits); + assert(pixmap_priv->fbo->tex); + __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex, + format, type, + x, y, w, h, + bits, pbo); return TRUE; } @@ -534,8 +529,8 @@ ready_to_upload: pixmap_priv_get_scale(pixmap_priv, &dst_xscale, &dst_yscale); glamor_set_normalize_vcoords(dst_xscale, dst_yscale, - 0, 0, - pixmap->drawable.width, pixmap->drawable.height, + x, y, + x + w, y + h, glamor_priv->yInverted, vertices); @@ -551,9 +546,10 @@ ready_to_upload: dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glamor_set_destination_pixmap_priv_nc(pixmap_priv); - dispatch->glGenTextures(1, &tex); - - __glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0, bits); + __glamor_upload_pixmap_to_texture(pixmap, &tex, + format, type, + 0, 0, w, h, + bits, pbo); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -589,40 +585,6 @@ ready_to_upload: return TRUE; } -/* - * Load texture from the pixmap's data pointer and then - * draw the texture to the fbo, and flip the y axis. - * */ - -static Bool -_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, int no_alpha, int revert, - int swap_rb) -{ - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - void *bits; - int need_free_bits = 0; - - if (!pixmap_priv) - return TRUE; - - 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); - - if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) - bits = NULL; - - return glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, - revert, swap_rb, - pixmap->devPrivate.ptr); -} - - /* * Prepare to upload a pixmap to texture memory. * no_alpha equals 1 means the format needs to wire alpha to 1. @@ -642,6 +604,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + if (pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb) + return 0; + if (!(no_alpha || (revert != REVERT_NONE) || (swap_rb != SWAP_NONE_UPLOADING) @@ -683,8 +648,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int return 0; } -enum glamor_pixmap_status -glamor_upload_pixmap_to_texture(PixmapPtr pixmap) +Bool +glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h, + int stride, void *bits, int pbo) { GLenum format, type; int no_alpha, revert, swap_rb; @@ -697,14 +663,40 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) &swap_rb, 1)) { glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); - return GLAMOR_UPLOAD_FAILED; + return TRUE; } if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) - return GLAMOR_UPLOAD_FAILED; + return FALSE; - if (_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - revert, swap_rb)) + return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb, + x, y, w, h, stride, bits, pbo); +} + +enum glamor_pixmap_status +glamor_upload_pixmap_to_texture(PixmapPtr pixmap) +{ + glamor_pixmap_private *pixmap_priv; + void *data; + int pbo; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (pixmap_priv + && (pixmap_priv->fbo) + && (pixmap_priv->fbo->pbo_valid)) { + data = NULL; + pbo = pixmap_priv->fbo->pbo; + } else { + data = pixmap->devPrivate.ptr; + pbo = 0; + } + + if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->devKind, + data, pbo)) return GLAMOR_UPLOAD_DONE; else return GLAMOR_UPLOAD_FAILED; @@ -715,20 +707,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) void glamor_restore_pixmap_to_texture(PixmapPtr pixmap) { - GLenum format, type; - int no_alpha, revert, swap_rb; - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, &no_alpha, - &revert, &swap_rb, 1)) { - ErrorF("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - assert(0); - } - - if (!_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, - revert, swap_rb)) + if (glamor_upload_pixmap_to_texture(pixmap) != GLAMOR_UPLOAD_DONE) LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n", pixmap->drawable.pScreen->myNum); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index cfa46e537..f89632cc1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -639,6 +639,10 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag); enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap); +Bool +glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h, + int stride, void *bits, int pbo); + PixmapPtr glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 010950e59..858fc0740 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -263,10 +263,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int x_off, y_off; float vertices[8], texcoords[8]; GLfloat xscale, yscale, txscale, tyscale; - GLuint tex; - int no_alpha, revert; Bool ret = FALSE; - int swap_rb; PixmapPtr temp_pixmap; glamor_pixmap_private *temp_pixmap_priv; @@ -288,37 +285,19 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, if (!glamor_set_planemask(pixmap, gc->planemask)) { goto fail; } - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, &no_alpha, - &revert, - &swap_rb, - 1)) { - glamor_fallback("unknown depth. %d \n", drawable->depth); - goto fail; - } - /* create a temporary pixmap and upload the bits to that * pixmap, then apply clip copy it to the destination pixmap.*/ temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); - if (temp_pixmap == NULL) goto fail; + temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + temp_pixmap_priv->pict_format = pixmap_priv->pict_format; + temp_pixmap_priv->is_picture = pixmap_priv->is_picture; - if (temp_pixmap_priv->fbo == NULL) { - glamor_destroy_pixmap(temp_pixmap); - goto fail; - } - - if (!glamor_upload_bits_to_pixmap_texture(temp_pixmap, format, type, - no_alpha, revert, swap_rb, bits)) { - glamor_destroy_pixmap(temp_pixmap); - goto fail; - } - + glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, + pixmap->devKind, bits, 0); dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, gc->alu)) { @@ -345,9 +324,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, #endif dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); dispatch->glUniform1i(glamor_priv-> - finish_access_revert[no_alpha], + finish_access_revert[0], REVERT_NONE); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], SWAP_NONE_UPLOADING); x += drawable->x; @@ -397,7 +376,6 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glDeleteTextures(1, &tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(dispatch, GXcopy); From b5bd9a2d902d44834fc43199167d7dee71c9b709 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 11 Apr 2012 18:57:33 +0800 Subject: [PATCH 333/462] glamor_upload/download: fix 1bpp bug. For A1 to A8's conversion, the stride is different for the source and destination. Previous implementation use the same stride, and may allocate less memory than required. Thus may crash the server when uploading a A1 pixmap. Now fix it. Tested-by: Peng Li Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 77fd033d9..0b2302194 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -217,13 +217,16 @@ _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int st PictFormatShort dst_format, src_format; pixman_image_t *dst_image; pixman_image_t *src_image; + int src_stride; if (revert == REVERT_UPLOADING_A1) { src_format = PICT_a1; dst_format = PICT_a8; + src_stride = PixmapBytePad(w, 1); } else { dst_format = PICT_a1; src_format = PICT_a8; + src_stride = (((w * 8 + 7) / 8) + 3) & ~3; } dst_image = pixman_image_create_bits(dst_format, @@ -238,7 +241,7 @@ _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int st src_image = pixman_image_create_bits(src_format, w, h, src_bits, - stride); + src_stride); if (src_image == NULL) { pixman_image_unref(dst_image); @@ -490,7 +493,13 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty && revert > REVERT_NORMAL) { /* XXX if we are restoring the pixmap, then we may not need to allocate * new buffer */ - void *converted_bits = malloc(h * stride); + void *converted_bits; + + if (pixmap->drawable.depth == 1) + stride = (((w * 8 + 7) / 8) + 3) & ~3; + + converted_bits = malloc(h * stride); + if (converted_bits == NULL) return FALSE; bits = glamor_color_convert_to_bits(bits, converted_bits, w, h, @@ -864,8 +873,9 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, need_post_conversion = (revert > REVERT_NORMAL); if (need_post_conversion) { if (pixmap->drawable.depth == 1) { - stride = (((w * 8 + 7) / 8) + 3) & ~3; - data = malloc(stride * h); + int temp_stride; + temp_stride = (((w * 8 + 7) / 8) + 3) & ~3; + data = malloc(temp_stride * h); if (data == NULL) return NULL; need_free_data = 1; @@ -877,13 +887,14 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h, format, type, no_alpha, - revert, swap_rb))) + revert, swap_rb))) { + free(data); return NULL; + } x = 0; y = 0; } - dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; @@ -954,7 +965,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, * Don't need to consider if the pbo is valid.*/ bits = glamor_color_convert_to_bits(data, bits, w, h, - stride, no_alpha, + stride, + no_alpha, revert, swap_rb); } From cf0e206a0ff6538eb286c06098023b9e29b00c74 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 11 Apr 2012 18:59:27 +0800 Subject: [PATCH 334/462] glamor_polylines: Don't fallback for non-solid fill. As glamor_fill/fbFill will handle non-solid fill correctly. We don't fallback it here. Signed-off-by: Zhigang Gong --- glamor/glamor_polylines.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 175e9580d..70dd6c161 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -54,13 +54,12 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, */ goto wide_line; } - if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) { + if (gc->lineStyle != LineSolid) { glamor_fallback - ("non-solid fill line style %d, fill style %d\n", - gc->lineStyle, gc->fillStyle); + ("non-solid fill line style %d\n", + gc->lineStyle); goto fail; } - rects = malloc(sizeof(xRectangle) * (n - 1)); x1 = points[0].x; y1 = points[0].y; From 428f2a3f58a91300835aaa083ac0b291ce394dd0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 13 Apr 2012 13:45:42 +0800 Subject: [PATCH 335/462] glamor_pixmap_ensure_fbo: Should allocate tex if we don't have one. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index e9612bd7f..e5b98a16c 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -527,7 +527,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_pixmap_attach_fbo(pixmap, fbo); } else { /* We do have a fbo, but it may lack of fb or tex. */ - if (pixmap_priv->fbo->tex) + if (!pixmap_priv->fbo->tex) pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, format); From 18d69fb0142088f7df230ec876c7ce2b55a41ad9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 13 Apr 2012 13:47:05 +0800 Subject: [PATCH 336/462] glamor_gl: Use GL_ALPHA for depth 8 pixmap. Use GL_RGBA to represent a8 pixmap is not efficient. Signed-off-by: Zhigang Gong --- glamor/glamor_priv.h | 2 +- glamor/glamor_utils.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index f89632cc1..961af472e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -185,7 +185,7 @@ struct glamor_saved_procs { #ifdef GLAMOR_GLES2 #define CACHE_FORMAT_COUNT 3 #else -#define CACHE_FORMAT_COUNT 1 +#define CACHE_FORMAT_COUNT 2 #endif #define CACHE_BUCKET_WCOUNT 4 diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 972918c08..da05143cf 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -257,10 +257,10 @@ static inline void gl_iformat_for_depth(int depth, GLenum * format) { switch (depth) { -#if 0 case 8: *format = GL_ALPHA; break; +#if 0 case 24: *format = GL_RGB; break; @@ -411,6 +411,8 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, inline static int cache_format(GLenum format) { switch (format) { + case GL_ALPHA: + return 1; case GL_RGBA: return 0; default: From 420af44a3aaefd4848aa24a28c330cab36049078 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 14 Apr 2012 22:40:48 +0800 Subject: [PATCH 337/462] Don't need to set GL_PACK_ROW_LENGTH/GL_UNPACK_ROW_LENGTH. We already adjust the stride of the pixmap, and keep the alignment as 4 should be ok to let the GL/GLES match the stride. Previous version has a unbalanced PACK ROW length seting, and is buggy, now fixed it. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 20 ++++++-------------- glamor/glamor_putimage.c | 2 -- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 0b2302194..35eb9c7a6 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -819,7 +819,6 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, int stride, void *bits, int pbo, glamor_access_t access) { glamor_pixmap_private *pixmap_priv; - unsigned int row_length; GLenum format, type, gl_access, gl_usage; int no_alpha, revert, swap_rb; void *data, *read; @@ -896,13 +895,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, } dispatch = glamor_get_dispatch(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - row_length = (stride * 8) / pixmap->drawable.bitsPerPixel; - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 1); - dispatch->glPixelStorei(GL_PACK_ROW_LENGTH, row_length); - } else { - dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); - } + dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4); + if (glamor_priv->has_pack_invert || glamor_priv->yInverted) { if (!glamor_priv->yInverted) { @@ -941,17 +935,15 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, temp_pbo); dispatch->glBufferData(GL_PIXEL_PACK_BUFFER, stride * - pixmap->drawable.height, + h, NULL, GL_STREAM_READ); - dispatch->glReadPixels(0, 0, row_length, - pixmap->drawable.height, + dispatch->glReadPixels(0, 0, w, h, format, type, 0); read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); for (yy = 0; yy < pixmap->drawable.height; yy++) memcpy(data + yy * stride, - read + (pixmap->drawable.height - - yy - 1) * stride, stride); + read + (h - yy - 1) * stride, stride); dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); dispatch->glDeleteBuffers(1, &temp_pbo); @@ -995,7 +987,7 @@ 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; + unsigned int stride, y; GLenum format, type, gl_access, gl_usage; int no_alpha, revert, swap_rb; void *data = NULL, *dst; diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 858fc0740..0d28b53c9 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -376,8 +376,6 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glamor_set_alu(dispatch, GXcopy); glamor_set_planemask(pixmap, ~0); glamor_put_dispatch(glamor_priv); From bd53e24dc32206dc978d3dc2408e1832f5a803e7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 22:47:48 +0800 Subject: [PATCH 338/462] glamor_pixmap_priv: Always return a valid private pixmap. If a pixmap doesn't have a private, then set its type to GLAMOR_MEMORY, and thus it will get a valid private. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 3 ++- glamor/glamor_priv.h | 9 ++++++++- glamor/glamor_utils.h | 1 - 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 9b1d425ea..d438b9c1e 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -67,7 +67,8 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv = dixLookupPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key); if (pixmap_priv == NULL) { pixmap_priv = calloc(sizeof(*pixmap_priv), 1); glamor_set_pixmap_private(pixmap, pixmap_priv); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 961af472e..9a153099d 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -370,8 +370,15 @@ glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv) static inline glamor_pixmap_private * glamor_get_pixmap_private(PixmapPtr pixmap) { - return dixLookupPrivate(&pixmap->devPrivates, + glamor_pixmap_private *priv; + priv = dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); + if (!priv) { + glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY); + priv = dixLookupPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key); + } + return priv; } void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index da05143cf..d2dc6e4eb 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -757,7 +757,6 @@ static inline void _glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int int stride = pixmap->devKind; p = p + y * stride + x; - ErrorF("devKind %d, x %d y %d w %d h %d width %d height %d\n", stride, x, y, w, h, pixmap->drawable.width, pixmap->drawable.height); for (i = 0; i < h; i++) { From e1be714312df8d596f6be268cb8a4e390e634c36 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 10:30:02 +0800 Subject: [PATCH 339/462] Fixed a unbalanced glamor_put_dispatch. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 35eb9c7a6..fbf159f85 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -1021,7 +1021,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) &pixmap_priv->fbo->pbo); glamor_put_dispatch(glamor_priv); pbo = pixmap_priv->fbo->pbo; - glamor_put_dispatch(glamor_priv); } dst = glamor_download_sub_pixmap_to_cpu(pixmap, 0, 0, From 70b71718e737872dfdbf4f6c7285d4260a099d17 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 14:36:09 +0800 Subject: [PATCH 340/462] glamor_putimage: Reuse copy area to do the clipped copy. If no clip set, we load the bits to the pixmap directly. Otherwise, load the bits to a temporary pixmap and call glamor_copy_area to do the clipped copy. Signed-off-by: Zhigang Gong --- glamor/glamor_putimage.c | 104 ++++++--------------------------------- 1 file changed, 16 insertions(+), 88 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 0d28b53c9..45c855044 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -288,99 +288,27 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, /* create a temporary pixmap and upload the bits to that * pixmap, then apply clip copy it to the destination pixmap.*/ - temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); - if (temp_pixmap == NULL) - goto fail; - - temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - temp_pixmap_priv->pict_format = pixmap_priv->pict_format; - temp_pixmap_priv->is_picture = pixmap_priv->is_picture; - - glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, - pixmap->devKind, bits, 0); - - dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, gc->alu)) { - glamor_put_dispatch(glamor_priv); - goto fail; - } - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); - -#ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); -#endif - dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); - dispatch->glUniform1i(glamor_priv-> - finish_access_revert[0], - REVERT_NONE); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], - SWAP_NONE_UPLOADING); - - x += drawable->x; - y += drawable->y; - - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); clip = fbGetCompositeClip(gc); + if (clip != NULL) { + temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); + if (temp_pixmap == NULL) + goto fail; - pixmap_priv_get_scale(temp_pixmap_priv, &txscale, &tyscale); - pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); + temp_pixmap_priv->pict_format = pixmap_priv->pict_format; + temp_pixmap_priv->is_picture = pixmap_priv->is_picture; - for (nbox = REGION_NUM_RECTS(clip), - pbox = REGION_RECTS(clip); nbox--; pbox++) { - int x1 = x; - int y1 = y; - int x2 = x + w; - int y2 = y + h; + glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, + pixmap->devKind, bits, 0); - if (x1 < pbox->x1) - x1 = pbox->x1; - if (y1 < pbox->y1) - y1 = pbox->y1; - if (x2 > pbox->x2) - x2 = pbox->x2; - if (y2 > pbox->y2) - y2 = pbox->y2; - if (x1 >= x2 || y1 >= y2) - continue; - - glamor_set_normalize_tcoords(txscale, tyscale, - x1 - x, y1 - y, - x2 - x, y2 - y, 1, texcoords); - - glamor_set_normalize_vcoords(xscale, yscale, - x1 + x_off, y1 + y_off, - x2 + x_off, y2 + y_off, - glamor_priv->yInverted, - vertices); - - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glamor_copy_area(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x, y); + glamor_destroy_pixmap(temp_pixmap); + } else { + ErrorF("put image directly. \n"); + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + glamor_upload_sub_pixmap_to_texture(pixmap, drawable->x + x_off, drawable->y + y_off, + w, h, pixmap->devKind, bits, 0); } - -#ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); -#endif - dispatch->glUseProgram(0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - - glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(pixmap, ~0); - glamor_put_dispatch(glamor_priv); - - glamor_destroy_pixmap(temp_pixmap); ret = TRUE; goto done; From ff3d2c796363ea603ab92995091a967a3f8636d7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 17:09:06 +0800 Subject: [PATCH 341/462] Fixed a stride problem for textured_drm pixmap. As a textured_drm pixmap has a drm bo attached to it, and it's the DDX layer to set it stride value. In some case, the stride value is not equal to PixmapBytePad(w, depth) which is used within glamor. Then if it is the case, we have two choice, one is to set the GL_PACK_ROW_LENGTH/GL_UNPACK_ROW_LENGTH when we need to download or upload the pixmap. The other option is to change the pixmap's devKind to match the one glamor is using when downloading the pixmap, and restore it to the drm stride after uploading the pixmap. We choose the 2nd option, as GLES doesn't support the first method. Signed-off-by: Zhigang Gong --- glamor/glamor_core.c | 3 +++ glamor/glamor_pixmap.c | 13 ++++++++++--- glamor/glamor_priv.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index f9c1db22f..009a0899b 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -344,6 +344,9 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) free(pixmap->devPrivate.ptr); } + if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) + pixmap->devKind = pixmap_priv->drm_stride; + if (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED) pixmap_priv->gl_fbo = GLAMOR_FBO_NORMAL; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index fbf159f85..db1b163d5 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -688,6 +688,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) glamor_pixmap_private *pixmap_priv; void *data; int pbo; + int ret; pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -706,11 +707,11 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap->drawable.height, pixmap->devKind, data, pbo)) - return GLAMOR_UPLOAD_DONE; + ret = GLAMOR_UPLOAD_DONE; else - return GLAMOR_UPLOAD_FAILED; + ret = GLAMOR_UPLOAD_FAILED; - return GLAMOR_UPLOAD_DONE; + return ret; } void @@ -1023,6 +1024,12 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) pbo = pixmap_priv->fbo->pbo; } + if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) { + stride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth); + pixmap_priv->drm_stride = pixmap->devKind; + pixmap->devKind = stride; + } + dst = glamor_download_sub_pixmap_to_cpu(pixmap, 0, 0, pixmap->drawable.width, pixmap->drawable.height, diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 9a153099d..46e4dc54c 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -327,6 +327,7 @@ typedef struct glamor_pixmap_private { PictFormatShort pict_format; glamor_pending_op pending_op; PixmapPtr container; + int drm_stride; glamor_screen_private *glamor_priv; } glamor_pixmap_private; From e38eb675321dce1bbc39cbd177a6398de567dd79 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 19:43:44 +0800 Subject: [PATCH 342/462] glamor_put_sub_pixmap: Change to use glamor_upload_sub_pixmap. As the pixmap may be attached to a picture, we need to use glamor_upload_sub_pixmap to process it. glamor_copy_n_to_n will not consider the picture case. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 32 +++++++++++++++++++------------- glamor/glamor_putimage.c | 7 +++++-- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index db1b163d5..e9e42c516 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -1170,6 +1170,11 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); pbo = sub_pixmap_priv ? (sub_pixmap_priv->fbo ? sub_pixmap_priv->fbo->pbo : 0): 0; + if (pixmap_priv->is_picture) { + sub_pixmap_priv->pict_format = pixmap_priv->pict_format; + sub_pixmap_priv->is_picture = pixmap_priv->is_picture; + } + if (pbo) data = NULL; else { @@ -1207,19 +1212,20 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces PixmapPtr glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access) { - struct pixman_box16 box; - int dx, dy; - box.x1 = x; - box.y1 = y; - box.x2 = x + w; - box.y2 = y + h; + void *bits; + int pbo; + glamor_pixmap_private *sub_pixmap_priv; - dx = -(x); - dy = -(y); - - glamor_copy_n_to_n(&sub_pixmap->drawable, - &pixmap->drawable, - NULL, &box, 1, dx, dy, - 0, 0, 0, NULL); + sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); + if (sub_pixmap_priv + && sub_pixmap_priv->fbo + && sub_pixmap_priv->fbo->pbo_valid) { + bits = NULL; + pbo = sub_pixmap_priv->fbo->pbo; + } else { + bits = sub_pixmap->devPrivate.ptr; + pbo = 0; + } + glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h, sub_pixmap->devKind, bits, pbo); glamor_destroy_pixmap(sub_pixmap); } diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 45c855044..cf8bf9929 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -295,8 +295,11 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, goto fail; temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - temp_pixmap_priv->pict_format = pixmap_priv->pict_format; - temp_pixmap_priv->is_picture = pixmap_priv->is_picture; + + if (pixmap_priv->is_picture) { + temp_pixmap_priv->pict_format = pixmap_priv->pict_format; + temp_pixmap_priv->is_picture = pixmap_priv->is_picture; + } glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, pixmap->devKind, bits, 0); From 68a5cc6f371e1f07ce176e154331dafaf5d9ef0e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 19:46:09 +0800 Subject: [PATCH 343/462] glamor_render: Don't download whole picture when fallback. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 25 ++++++++------- glamor/glamor_render.c | 69 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index e9e42c516..57974531c 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -674,7 +674,6 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h pixmap->drawable.depth); return TRUE; } - if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) return FALSE; @@ -1155,7 +1154,6 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return NULL; - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) flag = GLAMOR_CREATE_PIXMAP_CPU; else @@ -1215,17 +1213,18 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int void *bits; int pbo; glamor_pixmap_private *sub_pixmap_priv; - - sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); - if (sub_pixmap_priv - && sub_pixmap_priv->fbo - && sub_pixmap_priv->fbo->pbo_valid) { - bits = NULL; - pbo = sub_pixmap_priv->fbo->pbo; - } else { - bits = sub_pixmap->devPrivate.ptr; - pbo = 0; + if (access != GLAMOR_ACCESS_RO) { + sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); + if (sub_pixmap_priv + && sub_pixmap_priv->fbo + && sub_pixmap_priv->fbo->pbo_valid) { + bits = NULL; + pbo = sub_pixmap_priv->fbo->pbo; + } else { + bits = sub_pixmap->devPrivate.ptr; + pbo = 0; + } + glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h, sub_pixmap->devKind, bits, pbo); } - glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h, sub_pixmap->devKind, bits, pbo); glamor_destroy_pixmap(sub_pixmap); } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 9410adfee..3bf04d4f1 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -2816,6 +2816,16 @@ _glamor_composite(CARD8 op, RegionRec region; BoxPtr box; int nbox, i, ok; + PixmapPtr sub_dest_pixmap = NULL; + PixmapPtr sub_source_pixmap = NULL; + PixmapPtr sub_mask_pixmap = NULL; + int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y; + int source_x_off, source_y_off, saved_source_x, saved_source_y; + int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y; + DrawablePtr saved_dest_drawable; + DrawablePtr saved_source_drawable; + DrawablePtr saved_mask_drawable; + x_temp_src = x_source; y_temp_src = y_source; @@ -2824,10 +2834,6 @@ _glamor_composite(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - goto fail; - } - if (source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); @@ -2841,6 +2847,14 @@ _glamor_composite(CARD8 op, if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) goto fail; } + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + goto fail; + } + + if (op >= ARRAY_SIZE(composite_op_info)) + goto fail; + if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable @@ -3006,6 +3020,28 @@ fail: dest->pDrawable->width, dest->pDrawable->height, glamor_get_picture_location(dest)); +#define GET_SUB_PICTURE(p, access) do { \ + glamor_get_drawable_deltas(p->pDrawable, p ##_pixmap, \ + & p ##_x_off, & p ##_y_off); \ + sub_ ##p ##_pixmap = glamor_get_sub_pixmap(p ##_pixmap, \ + x_ ##p + p ##_x_off + p->pDrawable->x, \ + y_ ##p + p ##_y_off + p->pDrawable->y, \ + width, height, access); \ + if (sub_ ##p ##_pixmap != NULL) { \ + saved_ ##p ##_drawable = p->pDrawable; \ + p->pDrawable = &sub_ ##p ##_pixmap->drawable; \ + saved_ ##p ##_x = x_ ##p; \ + saved_ ##p ##_y = y_ ##p; \ + if (p->pCompositeClip) \ + pixman_region_translate (p->pCompositeClip, \ + p ##_x_off - x_ ##p, \ + p ##_y_off - y_ ##p); \ + x_ ##p = 0; \ + y_ ##p = 0; \ + } } while(0) + + GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); + if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_picture (source, GLAMOR_ACCESS_RO)) { @@ -3025,6 +3061,23 @@ fail: } glamor_finish_access_picture(dest, GLAMOR_ACCESS_RW); } + +#define PUT_SUB_PICTURE(p, access) do { \ + if (sub_ ##p ##_pixmap != NULL) { \ + x_ ##p = saved_ ##p ##_x; \ + y_ ##p = saved_ ##p ##_y; \ + if (p->pCompositeClip) \ + pixman_region_translate (p->pCompositeClip, \ + - p ## _x_off + x_ ##p, \ + - p ## _y_off + y_ ##p); \ + p->pDrawable = saved_ ##p ##_drawable; \ + glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap, \ + x_ ##p + p ##_x_off + p->pDrawable->x, \ + y_ ##p + p ##_y_off + p->pDrawable->y, \ + width, height, access); \ + }} while(0) + + PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); done: if (temp_src != source) FreePicture(temp_src, 0); @@ -3044,10 +3097,10 @@ glamor_composite(CARD8 op, INT16 y_source, INT16 x_mask, INT16 y_mask, - INT16 x_dest, INT16 y_dest, + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { - _glamor_composite(op, source, mask, dest, x_source, y_source, + _glamor_composite(op, source, mask, dest, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height, TRUE); } @@ -3061,10 +3114,10 @@ glamor_composite_nf(CARD8 op, INT16 y_source, INT16 x_mask, INT16 y_mask, - INT16 x_dest, INT16 y_dest, + INT16 x_dest, INT16 y_dest, CARD16 width, CARD16 height) { - return _glamor_composite(op, source, mask, dest, x_source, y_source, + return _glamor_composite(op, source, mask, dest, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height, FALSE); } From 65c5605c9693c8d30e597ac029be936495f23927 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 23:16:51 +0800 Subject: [PATCH 344/462] glamor_getspans: Reuse glamor_download_sub_pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_getspans.c | 66 +++++----------------------------------- 1 file changed, 8 insertions(+), 58 deletions(-) diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index bd6a5ec19..22e2b7c6b 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -34,74 +34,26 @@ _glamor_get_spans(DrawablePtr drawable, Bool fallback) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - GLenum format, type; - int no_alpha, revert; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch; - glamor_pixmap_fbo *temp_fbo = NULL; int i; uint8_t *readpixels_dst = (uint8_t *) dst; + void *data; int x_off, y_off; Bool ret = FALSE; - int swap_rb; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("pixmap has no fbo.\n"); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto fail; - } - - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, &no_alpha, - &revert, &swap_rb, 0)) { - glamor_fallback("unknown depth. %d \n", drawable->depth); - goto fail; - } - - if (revert > REVERT_NORMAL) - goto fail; - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); - - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && ( swap_rb != SWAP_NONE_DOWNLOADING - || revert != REVERT_NONE)) { - - /* XXX prepare whole pixmap is not efficient. */ - temp_fbo = - glamor_es2_pixmap_read_prepare(pixmap, 0, 0, pixmap->drawable.width, pixmap->drawable.height, format, - type, no_alpha, - revert, swap_rb); - if (temp_fbo == NULL) - goto fail; - - } glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - dispatch = glamor_get_dispatch(glamor_priv); for (i = 0; i < count; i++) { - if (glamor_priv->yInverted) { - dispatch->glReadPixels(points[i].x + x_off, - (points[i].y + y_off), - widths[i], 1, format, - type, readpixels_dst); - } else { - dispatch->glReadPixels(points[i].x + x_off, - pixmap->drawable.height - - 1 - (points[i].y + y_off), - widths[i], 1, format, - type, readpixels_dst); - } - readpixels_dst += - PixmapBytePad(widths[i], drawable->depth); + data = glamor_download_sub_pixmap_to_cpu(pixmap, points[i].x + x_off, + points[i].y + y_off, widths[i], 1, + PixmapBytePad(widths[i], drawable->depth), + readpixels_dst, 0, GLAMOR_ACCESS_RO); + assert(data == readpixels_dst); + readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } - glamor_put_dispatch(glamor_priv); - if (temp_fbo) - glamor_destroy_fbo(temp_fbo); ret = TRUE; goto done; @@ -112,8 +64,6 @@ fail: goto done; ret = TRUE; - 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); glamor_finish_access(drawable, GLAMOR_ACCESS_RO); From e15bc1207480d7d198862861d40af58903b4d0f0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 23:18:47 +0800 Subject: [PATCH 345/462] code clean up. Remove unused variables. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 9 --------- glamor/glamor_putimage.c | 8 -------- 2 files changed, 17 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index ddf057f59..af65826a4 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -36,30 +36,21 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, { PixmapPtr pixmap; struct glamor_pixmap_private *pixmap_priv; - struct glamor_screen_private *glamor_priv; int x_off, y_off; - GLenum tex_format, tex_type; - int no_alpha, revert; - glamor_pixmap_fbo *temp_fbo = NULL; - glamor_gl_dispatch * dispatch; Bool ret = FALSE; - int swap_rb; int stride; void *data; if (format != ZPixmap) goto fall_back; - glamor_priv = glamor_get_screen_private(drawable->pScreen); pixmap = glamor_get_drawable_pixmap(drawable); glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - if (!glamor_set_planemask(pixmap, planeMask)) { glamor_fallback ("Failedto set planemask in glamor_solid.\n"); goto fall_back; } - glamor_priv = glamor_get_screen_private(drawable->pScreen); pixmap_priv = glamor_get_pixmap_private(pixmap); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index cf8bf9929..011e077ff 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -249,20 +249,12 @@ static Bool _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int left_pad, int image_format, char *bits, Bool fallback) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - GLenum type, format, iformat; RegionPtr clip; - BoxPtr pbox; - int nbox; - int src_stride = PixmapBytePad(w, drawable->depth); int x_off, y_off; float vertices[8], texcoords[8]; - GLfloat xscale, yscale, txscale, tyscale; Bool ret = FALSE; PixmapPtr temp_pixmap; glamor_pixmap_private *temp_pixmap_priv; From 2806f1eaced851e4c88055c53d706f7beef8b555 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 23:49:38 +0800 Subject: [PATCH 346/462] glamor_setspans: Reuse glamor_upload_sub_pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_setspans.c | 60 ++++++++++------------------------------ 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index c5ecf85c5..e28385335 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -34,17 +34,12 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *dest_pixmap_priv; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(drawable->pScreen); - glamor_gl_dispatch *dispatch; - GLenum format, type; - int no_alpha, revert, i; + int i; uint8_t *drawpixels_src = (uint8_t *) src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; Bool ret = FALSE; - int swap_rb; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { @@ -52,57 +47,32 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, goto fail; } - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - glamor_fallback("ES2 fallback.\n"); - goto fail; - } - - if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, - &format, - &type, &no_alpha, - &revert, - &swap_rb, - 1)) { - glamor_fallback("unknown depth. %d \n", drawable->depth); - goto fail; - } - - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - glamor_validate_pixmap(dest_pixmap); + /* XXX Shall we set alu here? */ if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); - - dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, gc->alu)) { - glamor_put_dispatch(glamor_priv); - goto fail; - } - for (i = 0; i < n; i++) { n = REGION_NUM_RECTS(clip); pbox = REGION_RECTS(clip); while (n--) { - if (pbox->y1 > points[i].y) + int x1 = points[i].x; + int x2 = x1 + widths[i]; + int y1 = points[i].y; + + if (pbox->y1 > points[i].y || pbox->y2 < points[i].y) break; - dispatch->glScissor(pbox->x1, - points[i].y + y_off, - pbox->x2 - pbox->x1, 1); - dispatch->glEnable(GL_SCISSOR_TEST); - dispatch->glRasterPos2i(points[i].x + x_off, - points[i].y + y_off); - dispatch->glDrawPixels(widths[i], 1, format, - type, drawpixels_src); + x1 = x1 > pbox->x1 ? x1 : pbox->x1; + x2 = x2 < pbox->x2 ? x2 : pbox->x2; + if (x1 >= x2) + continue; + glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off, y1 + y_off, x2 - x1, 1, + PixmapBytePad(widths[i], drawable->depth), + drawpixels_src, 0); } - drawpixels_src += - PixmapBytePad(widths[i], drawable->depth); + drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } - glamor_set_planemask(dest_pixmap, ~0); - glamor_set_alu(dispatch, GXcopy); - dispatch->glDisable(GL_SCISSOR_TEST); - glamor_put_dispatch(glamor_priv); ret = TRUE; goto done; From 1761768f49a356f50645da53305e6b4bdef5c5f4 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sun, 15 Apr 2012 23:50:09 +0800 Subject: [PATCH 347/462] glamor_upload_pixmap: Use glTexImage2D for a fully update. Currently, intel's mesa dri driver will not check pbo for a TexSubImage2D. So we use glTexImage2D if we are a fully updating. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 57974531c..78d643a93 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -418,40 +418,40 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, int *tex, glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; + int non_sub = 0; + int iformat; dispatch = glamor_get_dispatch(glamor_priv); if (*tex == 0) { - int iformat; dispatch->glGenTextures(1, tex); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) gl_iformat_for_depth(pixmap->drawable.depth, &iformat); else iformat = format; + non_sub = 1; + assert(x == 0 && y == 0); + } - dispatch->glBindTexture(GL_TEXTURE_2D, *tex); - dispatch->glTexImage2D(GL_TEXTURE_2D, - 0, - iformat, - w, h, 0, format, type, - bits); - } else - dispatch->glBindTexture(GL_TEXTURE_2D, *tex); - + dispatch->glBindTexture(GL_TEXTURE_2D, *tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); - - dispatch->glTexSubImage2D(GL_TEXTURE_2D, - 0, x, y, w, h, - format, type, - bits); + if (non_sub) + dispatch->glTexImage2D(GL_TEXTURE_2D, + 0, iformat, w, h, 0, + format, type, + bits); + else + dispatch->glTexSubImage2D(GL_TEXTURE_2D, + 0, x, y, w, h, + format, type, + bits); if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); From 9bcddff93b79fd8978426d9832a5edd60ac410c0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 13 Apr 2012 18:15:49 +0800 Subject: [PATCH 348/462] pending_op: Remove the pending operations handling. We have disabled this feature for a long time, and previous testing shows that this(pending fill) will not bring observed performance gain. Now remove it. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 105 ++++++++++++++++----------------------- glamor/glamor_fbo.c | 6 --- glamor/glamor_fill.c | 14 +----- glamor/glamor_pixmap.c | 57 --------------------- glamor/glamor_priv.h | 28 +---------- glamor/glamor_render.c | 13 ----- glamor/glamor_tile.c | 75 ++++++++++++---------------- glamor/glamor_utils.h | 17 ------- 8 files changed, 76 insertions(+), 239 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index a373d3d0b..6599d6535 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -49,9 +49,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, } src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - if (src_pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL) - return FALSE; - if (gc) { if (gc->alu != GXcopy) { glamor_delayed_fallback(screen, "non-copy ALU\n"); @@ -69,10 +66,8 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, return FALSE; } - if (glamor_set_destination_pixmap(dst_pixmap)) { + if (glamor_set_destination_pixmap(dst_pixmap)) return FALSE; - } - glamor_validate_pixmap(dst_pixmap); dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, @@ -199,58 +194,48 @@ glamor_copy_n_to_n_textured(DrawablePtr src, return FALSE; } - if (alu != GXcopy) { - glamor_set_destination_pixmap_priv_nc (src_pixmap_priv); - glamor_validate_pixmap(src_pixmap); - } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - glamor_validate_pixmap(dst_pixmap); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), vertices); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, - &src_y_off); - dx += src_x_off; - dy += src_y_off; - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, - &src_yscale); + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, + &src_y_off); + dx += src_x_off; + dy += src_y_off; + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, + &src_yscale); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->fbo->tex); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, + src_pixmap_priv->fbo->tex); #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_BORDER); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_BORDER); + dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_BORDER); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_BORDER); #endif - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, - GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); - dispatch->glUniform1i(glamor_priv->finish_access_revert[0], - REVERT_NONE); - dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], - SWAP_NONE_UPLOADING); - } else { - GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, - src_pixmap_priv); - } + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); + dispatch->glUniform1i(glamor_priv->finish_access_revert[0], + REVERT_NONE); + dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], + SWAP_NONE_UPLOADING); for (i = 0; i < nbox; i++) { @@ -262,26 +247,22 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, vertices); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) - glamor_set_normalize_tcoords(src_xscale, - src_yscale, - box[i].x1 + dx, - box[i].y1 + dy, - box[i].x2 + dx, - box[i].y2 + dy, - glamor_priv->yInverted, - texcoords); - + glamor_set_normalize_tcoords(src_xscale, + src_yscale, + box[i].x1 + dx, + box[i].y1 + dy, + box[i].x2 + dx, + box[i].y2 + dy, + glamor_priv->yInverted, + texcoords); dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #ifndef GLAMOR_GLES2 - dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glDisable(GL_TEXTURE_2D); #endif - } dispatch->glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ if (flush_needed) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index e5b98a16c..e261cc2d9 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -538,12 +538,6 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) pixmap_priv = glamor_get_pixmap_private(pixmap); return TRUE; } -/* - * XXX how to handle those pending OPs. - * By default, pending OP is disabled. Maybe we will give up the pending - * OP latter. - * - * */ _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 3c171d458..95b070db0 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -213,20 +213,8 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, &color[1], &color[2], &color[3], format_for_pixmap(pixmap)); -#ifdef GLAMOR_DELAYED_FILLING - if (x == 0 && y == 0 - && width == pixmap->drawable.width - && height == pixmap->drawable.height - && pixmap_priv->fb != glamor_priv->screen_fbo) { - pixmap_priv->pending_op.type = GLAMOR_PENDING_FILL; - memcpy(&pixmap_priv->pending_op.fill.color4fv, - color, 4 * sizeof(GLfloat)); - pixmap_priv->pending_op.fill.colori = fg_pixel; - return TRUE; - } -#endif + glamor_set_destination_pixmap_priv_nc(pixmap_priv); - glamor_validate_pixmap(pixmap); dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, alu)) { diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 78d643a93..c2b196f6d 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -23,47 +23,10 @@ glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, } -static void -_glamor_pixmap_validate_filling(glamor_screen_private * glamor_priv, - glamor_pixmap_private * pixmap_priv) -{ - glamor_gl_dispatch *dispatch = glamor_get_dispatch(glamor_priv); - GLfloat vertices[8]; - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(glamor_priv->solid_prog); - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, - 1, pixmap_priv->pending_op.fill.color4fv); - vertices[0] = -1; - vertices[1] = -1; - vertices[2] = 1; - vertices[3] = -1; - vertices[4] = 1; - vertices[5] = 1; - vertices[6] = -1; - vertices[7] = 1; - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); - pixmap_priv->pending_op.type = GLAMOR_PENDING_NONE; - glamor_put_dispatch(glamor_priv); -} - - -glamor_pixmap_validate_function_t pixmap_validate_funcs[] = { - NULL, - _glamor_pixmap_validate_filling -}; - void glamor_pixmap_init(ScreenPtr screen) { - glamor_screen_private *glamor_priv; - glamor_priv = glamor_get_screen_private(screen); - glamor_priv->pixmap_validate_funcs = pixmap_validate_funcs; } void @@ -71,23 +34,6 @@ glamor_pixmap_fini(ScreenPtr screen) { } -void -glamor_validate_pixmap(PixmapPtr pixmap) -{ - glamor_pixmap_validate_function_t validate_op; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - - validate_op = - glamor_priv->pixmap_validate_funcs[pixmap_priv-> - pending_op.type]; - if (validate_op) { - (*validate_op) (glamor_priv, pixmap_priv); - } -} - void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo) { @@ -865,9 +811,6 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, } glamor_set_destination_pixmap_priv_nc(pixmap_priv); - /* XXX we may don't need to validate it on GPU here, - * we can just validate it on CPU. */ - glamor_validate_pixmap(pixmap); need_post_conversion = (revert > REVERT_NORMAL); if (need_post_conversion) { diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 46e4dc54c..68d361787 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -132,11 +132,6 @@ enum gradient_shader_type { struct glamor_screen_private; struct glamor_pixmap_private; -typedef void (*glamor_pixmap_validate_function_t) (struct - glamor_screen_private *, - struct - glamor_pixmap_private - *); enum glamor_gl_flavor { GLAMOR_GL_DESKTOP, // OPENGL API @@ -246,7 +241,6 @@ typedef struct glamor_screen_private { struct glamor_saved_procs saved_procs; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; - glamor_pixmap_validate_function_t *pixmap_validate_funcs; int flags; ScreenPtr screen; } glamor_screen_private; @@ -257,22 +251,6 @@ typedef enum glamor_access { GLAMOR_ACCESS_WO, } glamor_access_t; -enum _glamor_pending_op_type { - GLAMOR_PENDING_NONE, - GLAMOR_PENDING_FILL -}; - -typedef struct _glamor_pending_fill { - unsigned int type; - GLfloat color4fv[4]; - CARD32 colori; -} glamor_pending_fill; - -typedef union _glamor_pending_op { - unsigned int type; - glamor_pending_fill fill; -} glamor_pending_op; - #define GLAMOR_FBO_NORMAL 1 #define GLAMOR_FBO_DOWNLOADED 2 /* glamor_pixmap_fbo: @@ -315,7 +293,6 @@ typedef struct glamor_pixmap_fbo { * @gl_tex: The pixmap is in a gl texture originally. * @is_picture: The drawable is attached to a picture. * @pict_format: the corresponding picture's format. - * #pending_op: currently only support pending filling. * @container: The corresponding pixmap's pointer. **/ typedef struct glamor_pixmap_private { @@ -325,7 +302,6 @@ typedef struct glamor_pixmap_private { glamor_pixmap_type_t type; glamor_pixmap_fbo *fbo; PictFormatShort pict_format; - glamor_pending_op pending_op; PixmapPtr container; int drm_stride; glamor_screen_private *glamor_priv; @@ -682,8 +658,6 @@ Bool glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenu **/ void glamor_destroy_upload_pixmap(PixmapPtr pixmap); -void glamor_validate_pixmap(PixmapPtr pixmap); - int glamor_create_picture(PicturePtr picture); Bool @@ -754,7 +728,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, * this will increase performance obviously. */ #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -//#define GLAMOR_DELAYED_FILLING +#define GLAMOR_DELAYED_FILLING //#define GLAMOR_GRADIENT_SHADER diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 3bf04d4f1..0e82e98dc 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -997,12 +997,6 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("no texture in source\n"); goto fail; #endif - } else if (source_pixmap_priv->pending_op.type == - GLAMOR_PENDING_FILL) { - key.source = SHADER_SOURCE_SOLID; - memcpy(source_solid_color, - source_pixmap_priv->pending_op. - fill.color4fv, 4 * sizeof(float)); } } if (key.mask == SHADER_MASK_TEXTURE || @@ -1020,12 +1014,6 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("no texture in mask\n"); goto fail; #endif - } else if (mask_pixmap_priv->pending_op.type == - GLAMOR_PENDING_FILL) { - key.mask = SHADER_MASK_SOLID; - memcpy(mask_solid_color, - mask_pixmap_priv->pending_op.fill.color4fv, - 4 * sizeof(float)); } } #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD @@ -1103,7 +1091,6 @@ glamor_composite_with_shader(CARD8 op, } #endif glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - glamor_validate_pixmap(dest_pixmap); if (!glamor_set_composite_op(screen, op, dest, mask)) { goto fail; diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index be873ccc2..8e0955364 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -152,13 +152,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, goto fail; } - if (alu != GXcopy) { - glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); - glamor_validate_pixmap(tile); - } - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - glamor_validate_pixmap(pixmap); pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); dispatch = glamor_get_dispatch(glamor_priv); @@ -167,45 +161,40 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, goto fail; } - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, - &src_yscale); - dispatch->glUseProgram(glamor_priv->tile_prog); + pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, + &src_yscale); + dispatch->glUseProgram(glamor_priv->tile_prog); - wh[0] = (float)src_pixmap_priv->fbo->width / tile->drawable.width; - wh[1] = (float)src_pixmap_priv->fbo->height / tile->drawable.height; + wh[0] = (float)src_pixmap_priv->fbo->width / tile->drawable.width; + wh[1] = (float)src_pixmap_priv->fbo->height / tile->drawable.height; - dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); - dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->fbo->tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_REPEAT); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); + dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glBindTexture(GL_TEXTURE_2D, + src_pixmap_priv->fbo->tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_REPEAT); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); #ifndef GLAMOR_GLES2 - dispatch->glEnable(GL_TEXTURE_2D); + dispatch->glEnable(GL_TEXTURE_2D); #endif - glamor_set_normalize_tcoords(src_xscale, src_yscale, - tile_x1, tile_y1, - tile_x2, tile_y2, - glamor_priv->yInverted, - source_texcoords); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, - GL_FLOAT, GL_FALSE, - 2 * sizeof(float), - source_texcoords); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - } else { - GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, - src_pixmap_priv); - } + glamor_set_normalize_tcoords(src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + source_texcoords); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glamor_set_normalize_vcoords(dst_xscale, dst_yscale, x1, y1, x2, y2, @@ -217,12 +206,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if (GLAMOR_PIXMAP_PRIV_NO_PENDING(src_pixmap_priv)) { - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); #ifndef GLAMOR_GLES2 dispatch->glDisable(GL_TEXTURE_2D); #endif - } dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); glamor_set_alu(dispatch, GXcopy); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index d2dc6e4eb..27fe62847 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -207,23 +207,6 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) #define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED)) -#define GLAMOR_PIXMAP_PRIV_NEED_VALIDATE(pixmap_priv) \ - (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) \ - && (pixmap_priv->pending_op.type != GLAMOR_PENDING_NONE)) - -#define GLAMOR_PIXMAP_PRIV_NO_PENDING(pixmap_priv) \ - (pixmap_priv->pending_op.type == GLAMOR_PENDING_NONE) - -#define GLAMOR_CHECK_PENDING_FILL(_dispatch_, _glamor_priv_, _pixmap_priv_) do \ - { \ - if (_pixmap_priv_->pending_op.type == GLAMOR_PENDING_FILL) { \ - _dispatch_->glUseProgram(_glamor_priv_->solid_prog); \ - _dispatch_->glUniform4fv(_glamor_priv_->solid_color_uniform_location, 1, \ - _pixmap_priv_->pending_op.fill.color4fv); \ - } \ - } while(0) - - /** * Borrow from uxa. */ From 08e8c00fe6a21741ff9f38652c2b9fd2310f1ce5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 09:27:06 +0800 Subject: [PATCH 349/462] glamor_getimage: Don't fallback to miGetImage. As miGetImage is very inefficient, we don't fallback to it. If the format is not ZPixmap, we download the required sub- region, and then call fbGetImage to do the conversion. This way is much faster than previous. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index af65826a4..b53635c5c 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -34,18 +34,19 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d, Bool fallback) { - PixmapPtr pixmap; + PixmapPtr pixmap, sub_pixmap; struct glamor_pixmap_private *pixmap_priv; int x_off, y_off; Bool ret = FALSE; int stride; void *data; + pixmap = glamor_get_drawable_pixmap(drawable); + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + if (format != ZPixmap) goto fall_back; - pixmap = glamor_get_drawable_pixmap(drawable); - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); if (!glamor_set_planemask(pixmap, planeMask)) { glamor_fallback ("Failedto set planemask in glamor_solid.\n"); @@ -64,12 +65,22 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, stride, d, 0, GLAMOR_ACCESS_RO); if (data != NULL) { - ret = TRUE; assert(data == d); + return TRUE; } fall_back: - if (ret == FALSE) - miGetImage(drawable, x, y, w, h, format, planeMask, d); + sub_pixmap = glamor_get_sub_pixmap(pixmap, x + x_off + drawable->x, + y + y_off + drawable->y, w, h, + GLAMOR_ACCESS_RO); + if (sub_pixmap) { + fbGetImage(&sub_pixmap->drawable, 0, 0, w, h, format, planeMask, d); + glamor_put_sub_pixmap(sub_pixmap, pixmap, + x + x_off + drawable->x, + y + y_off + drawable->y, + w, h, GLAMOR_ACCESS_RO); + } else + fbGetImage(drawable, x, y, w, h, format, planeMask, d); + return TRUE; } From ea70ebe0ac9fe5b3d0ad553f9aeb4d2829bf9a62 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 11:56:43 +0800 Subject: [PATCH 350/462] Fixed one potential texture size mismatch problem. There are two cases which we may use a wrong texture size. 1. A pixmap is modified by the client side after it created it. Then the pixmap's width may mismatch the original fbo/tex's size. Thus we need to check this condition when preparing upload the pixmap. 2. We provide two API to download/upload sub region of a textured pixmap. The caller may pass in a larger width then the original pixmap's size, this may happen at putimage and setspans. We need to validate the width and height when do the downloading/uploading. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index c2b196f6d..6f66fb478 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -559,7 +559,14 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - if (pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb) + if (pixmap_priv->fbo + && (pixmap_priv->fbo->width < pixmap->drawable.width + || pixmap_priv->fbo->height < pixmap->drawable.height)) { + fbo = glamor_pixmap_detach_fbo(pixmap_priv); + glamor_destroy_fbo(fbo); + } + + if (pixmap_priv->fbo && pixmap_priv->fbo->fb) return 0; if (!(no_alpha @@ -1085,6 +1092,9 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces int pbo; int flag; + assert(x >= 0 && y >= 0); + w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w; + h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h; if (access == GLAMOR_ACCESS_WO) { sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); @@ -1167,6 +1177,10 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int bits = sub_pixmap->devPrivate.ptr; pbo = 0; } + + assert(x >= 0 && y >= 0); + w = (w > sub_pixmap->drawable.width) ? sub_pixmap->drawable.width : w; + h = (h > sub_pixmap->drawable.height) ? sub_pixmap->drawable.height : h; glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h, sub_pixmap->devKind, bits, pbo); } glamor_destroy_pixmap(sub_pixmap); From 05da99106b81465488c9879cfd709fd4f0c7b9e5 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 11:59:47 +0800 Subject: [PATCH 351/462] glamor_putimage: Optimize for direct uploading and fallback path. This commit optimize two cases: 1. When the clip contains the whole area, we can directly upload the texel data to the pixmap, and don't need to do one extra clipped copy. 2. At fallback path, we don't read back the whole pixmap, just need a sub region. Signed-off-by: Zhigang Gong --- glamor/glamor_putimage.c | 41 +++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 011e077ff..0c3c0c5ba 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -256,9 +256,12 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int x_off, y_off; float vertices[8], texcoords[8]; Bool ret = FALSE; - PixmapPtr temp_pixmap; + PixmapPtr temp_pixmap, sub_pixmap; glamor_pixmap_private *temp_pixmap_priv; + BoxRec box; + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); + clip = fbGetCompositeClip(gc); if (image_format == XYBitmap) { assert(depth == 1); goto fail; @@ -279,9 +282,13 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } /* create a temporary pixmap and upload the bits to that * pixmap, then apply clip copy it to the destination pixmap.*/ + box.x1 = x + drawable->x; + box.y1 = y + drawable->y; + box.x2 = x + w + drawable->x; + box.y2 = y + h + drawable->y; - clip = fbGetCompositeClip(gc); - if (clip != NULL) { + if ((clip != NULL && !RegionContainsRect(clip, &box)) + || gc->alu != GXcopy) { temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); if (temp_pixmap == NULL) goto fail; @@ -298,12 +305,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_copy_area(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x, y); glamor_destroy_pixmap(temp_pixmap); - } else { - ErrorF("put image directly. \n"); - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - glamor_upload_sub_pixmap_to_texture(pixmap, drawable->x + x_off, drawable->y + y_off, + } else + glamor_upload_sub_pixmap_to_texture(pixmap, x + drawable->x + x_off, y + drawable->y + y_off, w, h, pixmap->devKind, bits, 0); - } ret = TRUE; goto done; @@ -316,11 +320,26 @@ fail: glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) { + + sub_pixmap = glamor_get_sub_pixmap(pixmap, x + x_off + drawable->x, + y + y_off + drawable->y, w, h, + GLAMOR_ACCESS_RW); + if (sub_pixmap) { + if (clip != NULL) + pixman_region_translate (clip, -x - drawable->x, -y - drawable->y); + + fbPutImage(&sub_pixmap->drawable, gc, depth, 0, 0, w, h, + left_pad, image_format, bits); + + glamor_put_sub_pixmap(sub_pixmap, pixmap, + x + x_off + drawable->x, + y + y_off + drawable->y, + w, h, GLAMOR_ACCESS_RW); + if (clip != NULL) + pixman_region_translate (clip, x + drawable->x, y + drawable->y); + } else fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); - glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RW); - } ret = TRUE; done: From 3d96929596fd3a6da41aab5cb9d7fb1cf28b2a03 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Wed, 25 Apr 2012 14:25:39 +0800 Subject: [PATCH 352/462] Fix the problem of memory leak in gradient pixmap generating. Fix the problem of memory leak in gradient pixmap generating. The problem caused by we do not call glDeleteShader when destroy a shader program. This patch will split the gradient pixmap generating to three category. If nstops < 6, we will use the no array version of the shader, which has the best performance. Else if nstops < 16, we use array version of the shader, which is compiled and linked at screen init stage. Else if nstops > 16, we dynamically create a new shader program, and this program will be cached until bigger nstops. Signed-off-by: Zhigang Gong --- glamor/glamor_gl_dispatch.c | 1 + glamor/glamor_gl_dispatch.h | 1 + glamor/glamor_priv.h | 28 +++-- glamor/glamor_render.c | 238 +++++++++++++++++++++++++++--------- 4 files changed, 199 insertions(+), 69 deletions(-) diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index fc3c5c0a9..e6da94d9c 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -76,6 +76,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glCreateShader, get_proc_address); INIT_FUNC(dispatch, glCompileShader, get_proc_address); INIT_FUNC(dispatch, glAttachShader, get_proc_address); + INIT_FUNC(dispatch, glDeleteShader, get_proc_address); INIT_FUNC(dispatch, glGetShaderiv, get_proc_address); INIT_FUNC(dispatch, glGetShaderInfoLog, get_proc_address); INIT_FUNC(dispatch, glGetProgramiv, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index 6adbde99a..b3fc3a629 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -108,6 +108,7 @@ typedef struct glamor_gl_dispatch { GLuint (*glCreateShader) (GLenum type); void (*glCompileShader) (GLuint shader); void (*glAttachShader) (GLuint program, GLuint shader); + void (*glDeleteShader) (GLuint shader); void (*glGetShaderiv) (GLuint shader, GLenum pname, GLint * params); void (*glGetShaderInfoLog) (GLuint shader, GLsizei bufSize, diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 68d361787..a7d89a978 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -123,11 +123,18 @@ enum shader_in { SHADER_IN_COUNT, }; -enum gradient_shader_type { - GRADIENT_SHADER_LINEAR, - GRADIENT_SHADER_RADIAL, - GRADIENT_SHADER_CONICAL, - GRADIENT_SHADER_COUNT, +enum gradient_shader { + SHADER_GRADIENT_LINEAR, + SHADER_GRADIENT_RADIAL, + SHADER_GRADIENT_CONICAL, + SHADER_GRADIENT_COUNT, +}; + +enum gradient_shader_prog { + SHADER_GRADIENT_VS_PROG, + SHADER_GRADIENT_FS_MAIN_PROG, + SHADER_GRADIENT_FS_GETCOLOR_PROG, + SHADER_GRADIENT_PROG_COUNT, }; struct glamor_screen_private; @@ -228,8 +235,13 @@ typedef struct glamor_screen_private { GLint tile_prog; GLint tile_wh; - /* glamor gradient */ - GLint gradient_prog[GRADIENT_SHADER_COUNT]; + /* glamor gradient, 0 for small nstops, 1 for + large nstops and 2 for dynamic generate. */ + GLint gradient_prog[SHADER_GRADIENT_COUNT][3]; + GLint linear_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3]; + int linear_max_nstops; + GLint radial_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3]; + int radial_max_nstops; /* glamor_putimage */ GLint put_image_xybitmap_prog; @@ -729,7 +741,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #define GLAMOR_DELAYED_FILLING -//#define GLAMOR_GRADIENT_SHADER +#define GLAMOR_GRADIENT_SHADER diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 0e82e98dc..21186a813 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1412,11 +1412,12 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar return fs_getcolor_prog; } -static GLint -_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int use_array) +static void +_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) { glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; + int index; GLint gradient_prog = 0; char *gradient_fs = NULL; @@ -1564,12 +1565,35 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int us "}\n"; glamor_priv = glamor_get_screen_private(screen); + + if ((glamor_priv->radial_max_nstops >= stops_count) && (dyn_gen)) { + /* Very Good, not to generate again. */ + return; + } + + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) { + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; + + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]); + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0; + } + dispatch = glamor_get_dispatch(glamor_priv); gradient_prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(dispatch, - GL_VERTEX_SHADER, gradient_vs); + GL_VERTEX_SHADER, gradient_vs); XNFasprintf(&gradient_fs, gradient_fs_template, @@ -1580,8 +1604,8 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int us free(gradient_fs); - fs_getcolor_prog = _glamor_create_getcolor_fs_program(screen, - stops_count, use_array); + fs_getcolor_prog = + _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); dispatch->glAttachShader(gradient_prog, vs_prog); dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); @@ -1594,16 +1618,30 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int us dispatch->glUseProgram(0); + if (dyn_gen) { + index = 2; + glamor_priv->radial_max_nstops = stops_count; + } else if (stops_count) { + index = 1; + } else { + index = 0; + } + + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; + glamor_put_dispatch(glamor_priv); - return gradient_prog; } -static GLint -_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int use_array) +static void +_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) { glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; + int index = 0; GLint gradient_prog = 0; char *gradient_fs = NULL; GLint fs_main_prog, fs_getcolor_prog, vs_prog; @@ -1757,7 +1795,31 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us " gl_FragColor = get_color(stop_len);\n" "}\n"; + glamor_priv = glamor_get_screen_private(screen); + + if ((glamor_priv->linear_max_nstops >= stops_count) && (dyn_gen)) { + /* Very Good, not to generate again. */ + return; + } + + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) { + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; + + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]); + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0; + } + dispatch = glamor_get_dispatch(glamor_priv); gradient_prog = dispatch->glCreateProgram(); @@ -1773,8 +1835,8 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us GL_FRAGMENT_SHADER, gradient_fs); free(gradient_fs); - fs_getcolor_prog = _glamor_create_getcolor_fs_program(screen, - stops_count, use_array); + fs_getcolor_prog = + _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); dispatch->glAttachShader(gradient_prog, vs_prog); dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); @@ -1787,26 +1849,56 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int us dispatch->glUseProgram(0); + if (dyn_gen) { + index = 2; + glamor_priv->linear_max_nstops = stops_count; + } else if (stops_count) { + index = 1; + } else { + index = 0; + } + + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; + glamor_put_dispatch(glamor_priv); - return gradient_prog; } -#define LINEAR_DEFAULT_STOPS 6 + 2 -#define RADIAL_DEFAULT_STOPS 6 + 2 +#define LINEAR_SMALL_STOPS 6 + 2 +#define LINEAR_LARGE_STOPS 16 + 2 + +#define RADIAL_SMALL_STOPS 6 + 2 +#define RADIAL_LARGE_STOPS 16 + 2 void glamor_init_gradient_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv; + int i; glamor_priv = glamor_get_screen_private(screen); - glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR] = - _glamor_create_linear_gradient_program(screen, - LINEAR_DEFAULT_STOPS, 0); - glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL] = - _glamor_create_radial_gradient_program(screen, - RADIAL_DEFAULT_STOPS, 0); + for (i = 0; i < 3; i++) { + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; + + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; + } + glamor_priv->linear_max_nstops = 0; + glamor_priv->radial_max_nstops = 0; + + _glamor_create_linear_gradient_program(screen, 0, 0); + _glamor_create_linear_gradient_program(screen, LINEAR_LARGE_STOPS, 0); + + _glamor_create_radial_gradient_program(screen, 0, 0); + _glamor_create_radial_gradient_program(screen, RADIAL_LARGE_STOPS, 0); } void @@ -1814,14 +1906,44 @@ glamor_fini_gradient_shader(ScreenPtr screen) { glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; + int i = 0; glamor_priv = glamor_get_screen_private(screen); dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glDeleteProgram( - glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR]); - dispatch->glDeleteProgram( - glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL]); + for (i = 0; i < 3; i++) { + /* Linear Gradient */ + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); + + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); + + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); + + if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]) + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]); + + /* Radial Gradient */ + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); + + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); + + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); + + if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]) + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]); + } glamor_put_dispatch(glamor_priv); } @@ -2053,8 +2175,8 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; - GLfloat stop_colors_st[RADIAL_DEFAULT_STOPS*4]; - GLfloat n_stops_st[RADIAL_DEFAULT_STOPS]; + GLfloat stop_colors_st[RADIAL_SMALL_STOPS*4]; + GLfloat n_stops_st[RADIAL_SMALL_STOPS]; GLfloat A_value; GLfloat cxy[4]; float c1x, c1y, c2x, c2y, r1, r2; @@ -2110,15 +2232,17 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, ValidatePicture(dst_picture); - stops_count = src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS ? - src_picture->pSourcePict->radial.nstops + 2 : RADIAL_DEFAULT_STOPS; + stops_count = src_picture->pSourcePict->radial.nstops + 2; - /* Because the max value of nstops is unkown, so create a programwhen nstops > default.*/ - if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_DEFAULT_STOPS) { - gradient_prog = glamor_priv->gradient_prog[GRADIENT_SHADER_RADIAL]; + /* Because the max value of nstops is unkown, so create a program + when nstops > LINEAR_LARGE_STOPS.*/ + if (stops_count <= RADIAL_SMALL_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][0]; + } else if (stops_count <= RADIAL_LARGE_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][1]; } else { - gradient_prog = _glamor_create_radial_gradient_program(screen, - src_picture->pSourcePict->radial.nstops + 2, 1); + _glamor_create_radial_gradient_program(screen, src_picture->pSourcePict->linear.nstops + 2, 1); + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]; } /* Bind all the uniform vars .*/ @@ -2141,7 +2265,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, r2_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "r2"); - if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_DEFAULT_STOPS) { + if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) { stop0_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "stop0"); stop1_uniform_location = @@ -2204,7 +2328,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, goto GRADIENT_FAIL; /* Set all the stops and colors to shader. */ - if (stops_count > RADIAL_DEFAULT_STOPS) { + if (stops_count > RADIAL_SMALL_STOPS) { stop_colors = malloc(4 * stops_count * sizeof(float)); if (stop_colors == NULL) { ErrorF("Failed to allocate stop_colors memory.\n"); @@ -2224,7 +2348,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, stop_colors, n_stops); - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + if (src_picture->pSourcePict->linear.nstops + 2 <= RADIAL_SMALL_STOPS) { int j = 0; dispatch->glUniform4f(stop_color0_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], stop_colors[4*j+2], stop_colors[4*j+3]); @@ -2309,7 +2433,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, /* Do the clear logic.*/ - if (stops_count > RADIAL_DEFAULT_STOPS) { + if (stops_count > RADIAL_SMALL_STOPS) { free(n_stops); free(stop_colors); } @@ -2321,9 +2445,6 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(0); - if (src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS) - dispatch->glDeleteProgram(gradient_prog); - glamor_put_dispatch(glamor_priv); return dst_picture; @@ -2332,7 +2453,7 @@ GRADIENT_FAIL: FreePicture(dst_picture, 0); } - if (stops_count > RADIAL_DEFAULT_STOPS) { + if (stops_count > RADIAL_SMALL_STOPS) { if (n_stops) free(n_stops); if (stop_colors) @@ -2345,8 +2466,6 @@ GRADIENT_FAIL: dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(0); - if (src_picture->pSourcePict->radial.nstops + 2 > RADIAL_DEFAULT_STOPS) - dispatch->glDeleteProgram(gradient_prog); glamor_put_dispatch(glamor_priv); return NULL; } @@ -2381,8 +2500,8 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; - GLfloat stop_colors_st[LINEAR_DEFAULT_STOPS*4]; - GLfloat n_stops_st[LINEAR_DEFAULT_STOPS]; + GLfloat stop_colors_st[LINEAR_SMALL_STOPS*4]; + GLfloat n_stops_st[LINEAR_SMALL_STOPS]; GLint transform_mat_uniform_location; GLint pt1_uniform_location; @@ -2438,16 +2557,18 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, ValidatePicture(dst_picture); - stops_count = src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS ? - src_picture->pSourcePict->linear.nstops + 2 : LINEAR_DEFAULT_STOPS; + stops_count = src_picture->pSourcePict->linear.nstops + 2; /* Because the max value of nstops is unkown, so create a program - when nstops > default.*/ - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { - gradient_prog = glamor_priv->gradient_prog[GRADIENT_SHADER_LINEAR]; + when nstops > LINEAR_LARGE_STOPS.*/ + if (stops_count <= LINEAR_SMALL_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][0]; + } else if (stops_count <= LINEAR_LARGE_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][1]; } else { - gradient_prog = _glamor_create_linear_gradient_program(screen, - src_picture->pSourcePict->linear.nstops + 2, 1); + _glamor_create_linear_gradient_program(screen, + src_picture->pSourcePict->linear.nstops + 2, 1); + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]; } /* Bind all the uniform vars .*/ @@ -2472,7 +2593,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, pt_distance_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "pt_distance"); - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { stop0_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "stop0"); stop1_uniform_location = @@ -2555,7 +2676,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, DEBUGF("pt2:(%f %f)\n", pt2[0], pt2[1]); /* Set all the stops and colors to shader. */ - if (stops_count > LINEAR_DEFAULT_STOPS) { + if (stops_count > LINEAR_SMALL_STOPS) { stop_colors = malloc(4 * stops_count * sizeof(float)); if (stop_colors == NULL) { ErrorF("Failed to allocate stop_colors memory.\n"); @@ -2575,7 +2696,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, stop_colors, n_stops); - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_DEFAULT_STOPS) { + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { int j = 0; dispatch->glUniform4f(stop_color0_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], stop_colors[4*j+2], stop_colors[4*j+3]); @@ -2670,7 +2791,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, } /* Do the clear logic.*/ - if (stops_count > LINEAR_DEFAULT_STOPS) { + if (stops_count > LINEAR_SMALL_STOPS) { free(n_stops); free(stop_colors); } @@ -2682,9 +2803,6 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(0); - if (src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS) - dispatch->glDeleteProgram(gradient_prog); - glamor_put_dispatch(glamor_priv); return dst_picture; @@ -2693,7 +2811,7 @@ GRADIENT_FAIL: FreePicture(dst_picture, 0); } - if (stops_count > LINEAR_DEFAULT_STOPS) { + if (stops_count > LINEAR_SMALL_STOPS) { if (n_stops) free(n_stops); if (stop_colors) @@ -2706,8 +2824,6 @@ GRADIENT_FAIL: dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glUseProgram(0); - if (src_picture->pSourcePict->linear.nstops + 2 > LINEAR_DEFAULT_STOPS) - dispatch->glDeleteProgram(gradient_prog); glamor_put_dispatch(glamor_priv); return NULL; } From 686a322c76fa20ed45d5bbfc9742024300e83e7d Mon Sep 17 00:00:00 2001 From: Junyan He Date: Wed, 18 Apr 2012 08:04:26 +0800 Subject: [PATCH 353/462] Fix the bug caused by gradient picture set the stops at the same percentage. Fix the bug caused by gradient picture set the stops at the same percentage. The (stops[i] - stops[i-1]) will be used as divisor in the shader, which will cause problem. We just keep the later one if stops[i] == stops[i-1]. Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 21186a813..a01f9ee17 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -2074,26 +2074,35 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, static int _glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, - GLfloat *stop_colors, GLfloat *n_stops) + GLfloat *stop_colors, GLfloat *n_stops) { int i; - int count; + int count = 1; - for (i = 1; i < pgradient->nstops + 1; i++) { - stop_colors[i*4] = pixman_fixed_to_double( - pgradient->stops[i-1].color.red); - stop_colors[i*4+1] = pixman_fixed_to_double( - pgradient->stops[i-1].color.green); - stop_colors[i*4+2] = pixman_fixed_to_double( - pgradient->stops[i-1].color.blue); - stop_colors[i*4+3] = pixman_fixed_to_double( - pgradient->stops[i-1].color.alpha); + for (i = 0; i < pgradient->nstops; i++) { + /* We find some gradient picture set the stops at the same percentage, which + will cause the shader problem because the (stops[i] - stops[i-1]) will + be used as divisor. We just keep the later one if stops[i] == stops[i-1] */ + if (i < pgradient->nstops - 1 + && pgradient->stops[i].x == pgradient->stops[i+1].x) + continue; - n_stops[i] = (GLfloat)pixman_fixed_to_double( - pgradient->stops[i-1].x); + stop_colors[count*4] = pixman_fixed_to_double( + pgradient->stops[i].color.red); + stop_colors[count*4+1] = pixman_fixed_to_double( + pgradient->stops[i].color.green); + stop_colors[count*4+2] = pixman_fixed_to_double( + pgradient->stops[i].color.blue); + stop_colors[count*4+3] = pixman_fixed_to_double( + pgradient->stops[i].color.alpha); + + n_stops[count] = (GLfloat)pixman_fixed_to_double( + pgradient->stops[i].x); + count++; } - count = pgradient->nstops + 2; + /* for the end stop. */ + count++; switch (src_picture->repeatType) { #define REPEAT_FILL_STOPS(m, n) \ From 6b664dda69afa6c47ca083739093fa15fc674380 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 13:51:58 +0800 Subject: [PATCH 354/462] gradient: Disable gradient for gles2. As PVR glsl compiler seems doesn't support external fragment function, and fails at compile gradient shader. Disable it for now. We may need to modify gradient shader to don't use external function. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 ++ glamor/glamor_priv.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index d438b9c1e..cba662347 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -399,7 +399,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_tile_shader(screen); glamor_init_putimage_shaders(screen); glamor_init_finish_access_shaders(screen); +#ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); +#endif glamor_pixmap_init(screen); glamor_priv->flags = flags; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index a7d89a978..36bd9cda4 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -741,8 +741,8 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #define GLAMOR_DELAYED_FILLING +#ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER - - +#endif #endif /* GLAMOR_PRIV_H */ From 0b6867dddbed186c46048c610299ac0dde6a9ef0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 13:54:40 +0800 Subject: [PATCH 355/462] Disable A8 texture format for GLES2. As PVR's GLES2 implementation doesn't support A8 texture as rendering target, we disable it for now. Signed-off-by: Zhigang Gong --- glamor/glamor_utils.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 27fe62847..25ad99da2 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -240,13 +240,10 @@ static inline void gl_iformat_for_depth(int depth, GLenum * format) { switch (depth) { +#ifndef GLAMOR_GLES2 case 8: *format = GL_ALPHA; break; -#if 0 - case 24: - *format = GL_RGB; - break; #endif default: *format = GL_RGBA; From 8a85071edbd90780b286fa4b19205540fb276815 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 18:58:16 +0800 Subject: [PATCH 356/462] glamor_copyarea: Don't access a DRM only pixmap. As EGL image/gbm only support ARGB8888 image, we don't support other format. We may change the way to use gbm directly latter. But now, we have to face this limitation, and thus if a client create a 16bpp drawable, and call get texture from pixmap then a copy to here may occur and thus we have to force retur a TRUE without do nothing. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 6599d6535..d19e28b3c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -395,6 +395,13 @@ _glamor_copy_n_to_n(DrawablePtr src, && glamor_ddx_fallback_check_pixmap(dst)) goto done; + if (src_pixmap_priv->type == GLAMOR_DRM_ONLY + || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) { + LogMessage(X_WARNING, + "Access a DRM only pixmap is not allowed within glamor.\n", + dst->pScreen->myNum); + return TRUE; + } glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); From 67cf3838e4acd788b0ce413dcbe9896e2ca20e56 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 19:50:57 +0800 Subject: [PATCH 357/462] gradient: Don't need fixup flag when creating pixmap. Gradient can use a larger texture/fbo directly, don't need an eaxct size texture. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index a01f9ee17..fa6ef666b 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -2011,7 +2011,7 @@ _glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], static int _glamor_gradient_set_pixmap_destination(ScreenPtr screen, glamor_screen_private *glamor_priv, - PicturePtr dst_picure, + PicturePtr dst_picture, GLfloat *xscale, GLfloat *yscale, int x_source, int y_source, float vertices[8], @@ -2021,7 +2021,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, glamor_pixmap_private *pixmap_priv; PixmapPtr pixmap = NULL; - pixmap = glamor_get_drawable_pixmap(dst_picure->pDrawable); + pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ @@ -2039,24 +2039,24 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, DEBUGF("xscale = %f, yscale = %f," " x_source = %d, y_source = %d, width = %d, height = %d\n", *xscale, *yscale, x_source, y_source, - pixmap_priv->fbo->width, pixmap_priv->fbo->height); + dst_picture->pDrawable->width, dst_picture->pDrawable->height); glamor_set_normalize_vcoords(*xscale, *yscale, 0, 0, - (INT16)(pixmap_priv->fbo->width), - (INT16)(pixmap_priv->fbo->height), + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), glamor_priv->yInverted, vertices); if (tex_normalize) { glamor_set_normalize_tcoords(*xscale, *yscale, 0, 0, - (INT16)(pixmap_priv->fbo->width), - (INT16)(pixmap_priv->fbo->height), + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), glamor_priv->yInverted, tex_vertices); } else { glamor_set_tcoords(0, 0, - (INT16)(pixmap_priv->fbo->width), - (INT16)(pixmap_priv->fbo->height), + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), glamor_priv->yInverted, tex_vertices); } @@ -2224,7 +2224,7 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, pixmap = glamor_create_pixmap(screen, width, height, PIXMAN_FORMAT_DEPTH(format), - GLAMOR_CREATE_PIXMAP_FIXUP); + 0); if (!pixmap) goto GRADIENT_FAIL; @@ -2548,7 +2548,7 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, pixmap = glamor_create_pixmap(screen, width, height, PIXMAN_FORMAT_DEPTH(format), - GLAMOR_CREATE_PIXMAP_FIXUP); + 0); if (!pixmap) goto GRADIENT_FAIL; From 9f53cc1c3369fc61630b238f1b347a92fabf5a5a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 25 Apr 2012 22:35:12 +0800 Subject: [PATCH 358/462] glamor_render.c: Fixed repeatPad and repeatRelect. We should use difference calculation for these two repeat mode when we are a sub region within one texture. Signed-off-by: Zhigang Gong --- glamor/glamor_priv.h | 4 +- glamor/glamor_render.c | 119 +++++++++++++++++++++++++++++------------ 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 36bd9cda4..169436cc9 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -80,6 +80,8 @@ typedef struct glamor_composite_shader { GLint mask_uniform_location; GLint source_wh; GLint mask_wh; + GLint source_repeat_mode; + GLint mask_repeat_mode; } glamor_composite_shader; typedef struct { @@ -742,7 +744,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #define GLAMOR_DELAYED_FILLING #ifndef GLAMOR_GLES2 -#define GLAMOR_GRADIENT_SHADER +//#define GLAMOR_GRADIENT_SHADER #endif #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index fa6ef666b..d4ee78a69 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -70,13 +70,38 @@ static GLuint glamor_create_composite_fs(glamor_gl_dispatch * dispatch, struct shader_key *key) { + const char *repeat_define = + "#define RepeatNone 0\n" + "#define RepeatNormal 1\n" + "#define RepeatPad 2\n" + "#define RepeatReflect 3\n" + "uniform int source_repeat_mode;\n" + "uniform int mask_repeat_mode;\n"; const char *relocate_texture = GLAMOR_DEFAULT_PRECISION - "vec2 rel_tex_coord(vec2 texture, vec2 wh) \n" + "vec2 rel_tex_coord(vec2 texture, vec2 wh, int repeat) \n" "{\n" " vec2 rel_tex; \n" " rel_tex = texture * wh; \n" - " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n" + " if (repeat == RepeatNormal) \n" + " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n" + " else if(repeat == RepeatPad) { \n" + " if (rel_tex.x > 1.0) rel_tex.x = 1.0; \n" + " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n" + " if (rel_tex.y > 1.0) rel_tex.y = 1.0; \n" + " else if(rel_tex.y < 0.0) rel_tex.y = 0.0; \n" + " rel_tex = rel_tex / wh; \n" + " } \n" + " else if(repeat == RepeatReflect) {\n" + " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n" + " rel_tex.x = 2.0 - (1.0 - fract(rel_tex.x))/wh.x;\n" + " else \n" + " rel_tex.x = fract(rel_tex.x)/wh.x;\n" + " if ((1.0 - mod(abs(floor(rel_tex.y)), 2.0)) < 0.001)\n" + " rel_tex.y = 2.0 - (1.0 - fract(rel_tex.y))/wh.y;\n" + " else \n" + " rel_tex.y = fract(rel_tex.y)/wh.y;\n" + " } \n" " return rel_tex; \n" "}\n"; const char *source_solid_fetch = @@ -90,21 +115,25 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 source_wh;" "vec4 get_source()\n" "{\n" - " if (source_wh.x < 0.0) \n" + " if (source_repeat_mode == RepeatNone) \n" " return texture2D(source_sampler, source_texture);\n" " else \n" - " return texture2D(source_sampler, rel_tex_coord(source_texture, source_wh));\n" + " return texture2D(source_sampler,\n" + " rel_tex_coord(source_texture,\n" + " source_wh, source_repeat_mode));\n" "}\n"; const char *source_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" - "uniform vec2 source_wh;" + "uniform vec2 source_wh;\n" "vec4 get_source()\n" "{\n" - " if (source_wh.x < 0.0) \n" + " if (source_repeat_mode == RepeatNone) \n" " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" " else \n" - " return vec4(texture2D(source_sampler, rel_tex_coord(source_texture, source_wh)).rgb, 1);\n" + " return vec4(texture2D(source_sampler, \n" + " rel_tex_coord(source_texture,\n" + " source_wh, source_repeat_mode)).rgb, 1);\n" "}\n"; const char *mask_solid_fetch = GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" @@ -112,24 +141,28 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, const char *mask_alpha_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" - "uniform vec2 mask_wh;" + "uniform vec2 mask_wh;\n" "vec4 get_mask()\n" "{\n" - " if (mask_wh.x < 0.0) \n" + " if (mask_repeat_mode == RepeatNone) \n" " return texture2D(mask_sampler, mask_texture);\n" " else \n" - " return texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh));\n" + " return texture2D(mask_sampler, \n" + " rel_tex_coord(mask_texture, \n" + " mask_wh, mask_repeat_mode));\n" "}\n"; const char *mask_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" - "uniform vec2 mask_wh;" + "uniform vec2 mask_wh;\n" "vec4 get_mask()\n" "{\n" - " if (mask_wh.x < 0.0) \n" + " if (mask_repeat_mode == RepeatNone) \n" " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" " else \n" - " return vec4(texture2D(mask_sampler, rel_tex_coord(mask_texture, mask_wh)).rgb, 1);\n" + " return vec4(texture2D(mask_sampler, \n" + " rel_tex_coord(mask_texture, \n" + " mask_wh, mask_repeat_mode)).rgb, 1);\n" "}\n"; const char *in_source_only = GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" @@ -196,7 +229,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, FatalError("Bad composite IN type"); } - XNFasprintf(&source, "%s%s%s%s", relocate_texture, source_fetch, mask_fetch, in); + XNFasprintf(&source, "%s%s%s%s%s", repeat_define, relocate_texture, source_fetch, mask_fetch, in); prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, @@ -288,6 +321,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, dispatch->glGetUniformLocation(prog, "source_sampler"); dispatch->glUniform1i(source_sampler_uniform_location, 0); shader->source_wh = dispatch->glGetUniformLocation(prog, "source_wh"); + shader->source_repeat_mode = dispatch->glGetUniformLocation(prog, "source_repeat_mode"); } if (key->mask != SHADER_MASK_NONE) { @@ -301,6 +335,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key, dispatch->glUniform1i (mask_sampler_uniform_location, 1); shader->mask_wh = dispatch->glGetUniformLocation(prog, "mask_wh"); + shader->mask_repeat_mode = dispatch->glGetUniformLocation(prog, "mask_repeat_mode"); } } @@ -482,7 +517,7 @@ static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, glamor_pixmap_private * pixmap_priv, - GLuint wh_location) + GLuint wh_location, GLuint repeat_location) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); @@ -546,17 +581,18 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - if (picture->repeatType == RepeatNone) + if (picture->repeatType == RepeatNone) { has_repeat = picture->transform && !pixman_transform_is_int_translate(picture->transform); - else - has_repeat = TRUE; - if (has_repeat) { - wh[0] = (float)pixmap_priv->fbo->width / pixmap_priv->container->drawable.width; - wh[1] = (float)pixmap_priv->fbo->height / pixmap_priv->container->drawable.height; + if (has_repeat) + dispatch->glUniform1i(repeat_location, RepeatNormal); } - else - wh[0] = -1; + else { + has_repeat = TRUE; + dispatch->glUniform1i(repeat_location, picture->repeatType); + } + wh[0] = (float)pixmap_priv->fbo->width / pixmap_priv->container->drawable.width; + wh[1] = (float)pixmap_priv->fbo->height / pixmap_priv->container->drawable.height; dispatch->glUniform2fv(wh_location, 1, wh); glamor_put_dispatch(glamor_priv); } @@ -1111,7 +1147,8 @@ glamor_composite_with_shader(CARD8 op, shader->source_uniform_location); } else { glamor_set_composite_texture(screen, 0, source, - source_pixmap_priv, shader->source_wh); + source_pixmap_priv, shader->source_wh, + shader->source_repeat_mode); } if (key.mask != SHADER_MASK_NONE) { if (key.mask == SHADER_MASK_SOLID) { @@ -1120,7 +1157,8 @@ glamor_composite_with_shader(CARD8 op, shader->mask_uniform_location); } else { glamor_set_composite_texture(screen, 1, mask, - mask_pixmap_priv, shader->mask_wh); + mask_pixmap_priv, shader->mask_wh, + shader->mask_repeat_mode); } } @@ -2946,6 +2984,7 @@ _glamor_composite(CARD8 op, dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ + if (source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); @@ -2967,6 +3006,10 @@ _glamor_composite(CARD8 op, if (op >= ARRAY_SIZE(composite_op_info)) goto fail; + /*XXXXX, maybe we can make a copy of dest pixmap.*/ + if (source_pixmap == dest_pixmap) + goto full_fallback; + if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable @@ -3050,6 +3093,7 @@ _glamor_composite(CARD8 op, height)) goto done; } + x_dest += dest->pDrawable->x; y_dest += dest->pDrawable->y; if (temp_src->pDrawable) { @@ -3146,16 +3190,21 @@ fail: saved_ ##p ##_y = y_ ##p; \ if (p->pCompositeClip) \ pixman_region_translate (p->pCompositeClip, \ - p ##_x_off - x_ ##p, \ - p ##_y_off - y_ ##p); \ + -p->pDrawable->x - x_ ##p, \ + -p->pDrawable->y - y_ ##p); \ x_ ##p = 0; \ y_ ##p = 0; \ } } while(0) GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); + if (source->pDrawable) + GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); + if (mask && mask->pDrawable) + GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); +full_fallback: if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { - if (glamor_prepare_access_picture + if (source_pixmap == dest_pixmap || glamor_prepare_access_picture (source, GLAMOR_ACCESS_RO)) { if (!mask || glamor_prepare_access_picture(mask, @@ -3169,7 +3218,8 @@ fail: if (mask) glamor_finish_access_picture(mask, GLAMOR_ACCESS_RO); } - glamor_finish_access_picture(source, GLAMOR_ACCESS_RO); + if (source_pixmap != dest_pixmap) + glamor_finish_access_picture(source, GLAMOR_ACCESS_RO); } glamor_finish_access_picture(dest, GLAMOR_ACCESS_RW); } @@ -3180,15 +3230,18 @@ fail: y_ ##p = saved_ ##p ##_y; \ if (p->pCompositeClip) \ pixman_region_translate (p->pCompositeClip, \ - - p ## _x_off + x_ ##p, \ - - p ## _y_off + y_ ##p); \ + p->pDrawable->x + x_ ##p, \ + p->pDrawable->y + y_ ##p); \ p->pDrawable = saved_ ##p ##_drawable; \ glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap, \ x_ ##p + p ##_x_off + p->pDrawable->x, \ y_ ##p + p ##_y_off + p->pDrawable->y, \ width, height, access); \ }} while(0) - + if (mask && mask->pDrawable) + PUT_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); + if (source->pDrawable) + PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO); PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); done: if (temp_src != source) @@ -3442,6 +3495,4 @@ glamor_composite_rects_nf (CARD8 op, return _glamor_composite_rects(op, pDst, color, nRect, rects, FALSE); } - - #endif /* RENDER */ From 540846204cce9239233c5608a29bfe0607d77e44 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 26 Apr 2012 18:28:17 +0800 Subject: [PATCH 359/462] Fixed a1 bug. It seems that mesa has bugs when uploading bitmap to texture. We switch to convert bitmap to a8 format and then upload the a8 texture. Also added a helper routine to dump 1bpp pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 3 +-- glamor/glamor_utils.h | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 6f66fb478..68a7b0638 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -435,8 +435,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty if (bits == NULL) goto ready_to_upload; - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - && revert > REVERT_NORMAL) { + if (revert > REVERT_NORMAL) { /* XXX if we are restoring the pixmap, then we may not need to allocate * new buffer */ void *converted_bits; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 25ad99da2..c46849090 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -241,6 +241,7 @@ gl_iformat_for_depth(int depth, GLenum * format) { switch (depth) { #ifndef GLAMOR_GLES2 + case 1: case 8: *format = GL_ALPHA; break; @@ -286,6 +287,9 @@ format_for_pixmap(PixmapPtr pixmap) * Map picture's format to the correct gl texture format and type. * no_alpha is used to indicate whehter we need to wire alpha to 1. * + * Although opengl support A1/GL_BITMAP, we still don't use it + * here, it seems that mesa has bugs when uploading a A1 bitmap. + * * Return 0 if find a matched texture type. Otherwise return -1. **/ #ifndef GLAMOR_GLES2 @@ -304,8 +308,9 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format, *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING; switch (format) { case PICT_a1: - *tex_format = GL_COLOR_INDEX; - *tex_type = GL_BITMAP; + *tex_format = GL_ALPHA; + *tex_type = GL_UNSIGNED_BYTE; + *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1; break; case PICT_b8g8r8x8: *no_alpha = 1; @@ -730,6 +735,24 @@ inline static Bool glamor_tex_format_is_readable(GLenum format) } +static inline void _glamor_dump_pixmap_bits(PixmapPtr pixmap, int x, int y, int w, int h) +{ + int i,j; + unsigned char * p = pixmap->devPrivate.ptr; + int stride = pixmap->devKind; + + p = p + y * stride + x; + + for (i = 0; i < h; i++) + { + ErrorF("line %3d: ", i); + for(j = 0; j < w; j++) + ErrorF("%2d ", (p[j/8] & (1 << (j%8)))>>(j%8)); + p += stride; + ErrorF("\n"); + } +} + static inline void _glamor_dump_pixmap_byte(PixmapPtr pixmap, int x, int y, int w, int h) { int i,j; @@ -803,6 +826,9 @@ static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int case 32: _glamor_dump_pixmap_word(pixmap, x, y, w, h); break; + case 1: + _glamor_dump_pixmap_bits(pixmap, x, y, w, h); + break; default: ErrorF("dump depth %d, not implemented.\n", pixmap->drawable.depth); } From 6e50ee9c108e6d7ce4ebfcd08cfc97896e8e194e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 26 Apr 2012 18:31:07 +0800 Subject: [PATCH 360/462] glamor_fbo: Added a threshold value for the fbo cache pool. Currently set it to 256MB. If cache pool watermark increases to this value, then don't push any fbo to this pool, will purge the fbo directly. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 25 ++++++++++++++++++++----- glamor/glamor_priv.h | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index e261cc2d9..a7cae664d 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -9,6 +9,7 @@ #define GLAMOR_CACHE_TEXTURE 2 //#define NO_FBO_CACHE 1 +#define FBO_CACHE_THRESHOLD (256*1024*1024) /* Loop from the tail to the head. */ #define xorg_list_for_each_entry_reverse(pos, head, member) \ @@ -68,7 +69,7 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag) { struct xorg_list *cache; - glamor_pixmap_fbo *fbo_entry; + glamor_pixmap_fbo *fbo_entry, *ret_fbo = NULL; int size; int n_format; #ifdef NO_FBO_CACHE @@ -94,7 +95,8 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, fbo_entry, fbo_entry->width, fbo_entry->height, fbo_entry->fb, fbo_entry->tex); xorg_list_del(&fbo_entry->list); - return fbo_entry; + ret_fbo = fbo_entry; + break; } } } @@ -108,12 +110,18 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, fbo_entry->fb, fbo_entry->tex, fbo_entry->format); assert(format == fbo_entry->format); xorg_list_del(&fbo_entry->list); - return fbo_entry; + ret_fbo = fbo_entry; + break; } } } - return NULL; + if (ret_fbo) + glamor_priv->fbo_cache_watermark -= ret_fbo->width * ret_fbo->height; + + assert(glamor_priv->fbo_cache_watermark >= 0); + + return ret_fbo; #endif } @@ -144,7 +152,9 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) #else n_format = cache_format(fbo->format); - if (fbo->fb == 0 || n_format == -1) { + if (fbo->fb == 0 || n_format == -1 + || fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) { + fbo->glamor_priv->tick ++; glamor_purge_fbo(fbo); return; } @@ -159,6 +169,8 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) [cache_hbucket(fbo->height)]; DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); + + fbo->glamor_priv->fbo_cache_watermark += fbo->width * fbo->height; xorg_list_add(&fbo->list, cache); fbo->expire = fbo->glamor_priv->tick + GLAMOR_CACHE_EXPIRE_MAX; #endif @@ -264,6 +276,8 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) empty_cache = FALSE; break; } + + glamor_priv->fbo_cache_watermark -= fbo_entry->width * fbo_entry->height; xorg_list_del(&fbo_entry->list); DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, fbo_entry->expire, glamor_priv->tick); @@ -300,6 +314,7 @@ glamor_init_pixmap_fbo(ScreenPtr screen) xorg_list_init(&glamor_priv->fbo_cache[i][j][k]); xorg_list_init(&glamor_priv->tex_cache[i][j][k]); } + glamor_priv->fbo_cache_watermark = 0; } void diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 169436cc9..2aa03d005 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -209,6 +209,7 @@ typedef struct glamor_screen_private { struct xorg_list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; struct xorg_list tex_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; + unsigned long fbo_cache_watermark; /* glamor_solid */ GLint solid_prog; @@ -742,7 +743,6 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, * this will increase performance obviously. */ #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -#define GLAMOR_DELAYED_FILLING #ifndef GLAMOR_GLES2 //#define GLAMOR_GRADIENT_SHADER #endif From 20cbaa61cdca41e61526a57f13475cb31e17e5dd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 26 Apr 2012 19:57:21 +0800 Subject: [PATCH 361/462] glamor_render: Have to use eaxct size pixmap for transformation. Use partial texture as the pixmap for the transformation source/mask may introduce extra errors. have to use eaxct size. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 49 ++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index d4ee78a69..21ef904ab 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -522,12 +522,12 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; + float wh[2]; + Bool has_repeat; dispatch = glamor_get_dispatch(glamor_priv); dispatch->glActiveTexture(GL_TEXTURE0 + unit); dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); - float wh[2]; - Bool has_repeat; switch (picture->repeatType) { case RepeatNone: @@ -581,19 +581,14 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - if (picture->repeatType == RepeatNone) { - has_repeat = picture->transform - && !pixman_transform_is_int_translate(picture->transform); - if (has_repeat) - dispatch->glUniform1i(repeat_location, RepeatNormal); + dispatch->glUniform1i(repeat_location, picture->repeatType); + if (picture->repeatType != RepeatNone) { + wh[0] = (float)pixmap_priv->fbo->width + / pixmap_priv->container->drawable.width; + wh[1] = (float)pixmap_priv->fbo->height + / pixmap_priv->container->drawable.height; + dispatch->glUniform2fv(wh_location, 1, wh); } - else { - has_repeat = TRUE; - dispatch->glUniform1i(repeat_location, picture->repeatType); - } - wh[0] = (float)pixmap_priv->fbo->width / pixmap_priv->container->drawable.width; - wh[1] = (float)pixmap_priv->fbo->height / pixmap_priv->container->drawable.height; - dispatch->glUniform2fv(wh_location, 1, wh); glamor_put_dispatch(glamor_priv); } @@ -699,7 +694,6 @@ glamor_composite_with_copy(CARD8 op, if (region.extents.y2 + y_source - y_dest > source->pDrawable->height) goto cleanup_region; } - ret = glamor_copy_n_to_n_nf(source->pDrawable, dest->pDrawable, NULL, REGION_RECTS(®ion), @@ -1126,6 +1120,22 @@ glamor_composite_with_shader(CARD8 op, } } #endif + + /*Before enter the rendering stage, we need to fixup + * transformed source and mask, if the transform is not int translate. */ + if (key.source != SHADER_SOURCE_SOLID + && source->transform + && !pixman_transform_is_int_translate(source->transform)) { + if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) + goto fail; + } + if (key.mask != SHADER_SOURCE_SOLID && key.mask != SHADER_MASK_SOLID + && mask->transform + && !pixman_transform_is_int_translate(mask->transform)) { + if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) + goto fail; + } + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); if (!glamor_set_composite_op(screen, op, dest, mask)) { @@ -3006,10 +3016,6 @@ _glamor_composite(CARD8 op, if (op >= ARRAY_SIZE(composite_op_info)) goto fail; - /*XXXXX, maybe we can make a copy of dest pixmap.*/ - if (source_pixmap == dest_pixmap) - goto full_fallback; - if ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable @@ -3086,6 +3092,7 @@ _glamor_composite(CARD8 op, goto fail; } } + if (!mask) { if (glamor_composite_with_copy(op, temp_src, dest, x_temp_src, y_temp_src, @@ -3094,6 +3101,10 @@ _glamor_composite(CARD8 op, goto done; } + /*XXXXX, maybe we can make a copy of dest pixmap.*/ + if (source_pixmap == dest_pixmap) + goto full_fallback; + x_dest += dest->pDrawable->x; y_dest += dest->pDrawable->y; if (temp_src->pDrawable) { From 1f83411c9a69a44944fd8afe0c167cece60c1ecb Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 26 Apr 2012 19:59:58 +0800 Subject: [PATCH 362/462] glamor_copyarea: Return earlier if have zero nbox. Almost all callers will check whether the regions is empty before call to this internal API, but it seems the glamor_composite_with_copy may call into here with a zero nbox. A little weird, as the miComputeCompositeRegion return a Non-NULL, but the region is empty. Also remove a unecessary glflush. So let's check it here. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index d19e28b3c..f28206791 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -150,7 +150,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, int src_x_off, src_y_off, dst_x_off, dst_y_off; enum glamor_pixmap_status src_status = GLAMOR_NONE; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; - int flush_needed = 0; int alu = GXcopy; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); @@ -172,8 +171,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); #endif - } else - flush_needed = 1; + } if (gc) { if (!glamor_set_planemask(dst_pixmap, gc->planemask)) @@ -265,8 +263,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, #endif dispatch->glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ - if (flush_needed) - dispatch->glFlush(); glamor_put_dispatch(glamor_priv); return TRUE; } @@ -297,12 +293,13 @@ _glamor_copy_n_to_n(DrawablePtr src, int overlaped = 0; Bool ret = FALSE; + if (nbox == 0) + return TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; - glamor_priv = glamor_get_screen_private(dst->pScreen); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { From 9fcd123aed80430b220fc4141eaa3723d7cb611e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 26 Apr 2012 20:35:09 +0800 Subject: [PATCH 363/462] glamor_blockhandler: Don't do glFinish every time. To do glfinish every time bring some performance overhead. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index cba662347..ea822f318 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -213,7 +213,6 @@ glamor_block_handler(ScreenPtr screen) dispatch = glamor_get_dispatch(glamor_priv); glamor_priv->tick++; dispatch->glFlush(); - dispatch->glFinish(); glamor_fbo_expire(glamor_priv); glamor_put_dispatch(glamor_priv); } @@ -225,7 +224,6 @@ _glamor_block_handler(void *data, OSTimePtr timeout, glamor_screen_private *glamor_priv = data; glamor_gl_dispatch *dispatch = glamor_get_dispatch(glamor_priv); dispatch->glFlush(); - dispatch->glFinish(); glamor_put_dispatch(glamor_priv); } From 9dfd10dc75efdf4c26b7ff46b55e4a2d2453803b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 27 Apr 2012 15:34:15 +0800 Subject: [PATCH 364/462] glamor_render: Fix the repeat none for GLES2. As GLES2 doesn't support clamp to the border, we have to handle it seprately from the normal case. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 88 ++++++++++++++++++++++++++++-------------- glamor/glamor_utils.h | 11 ++++++ 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 21ef904ab..de01aab33 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -65,7 +65,7 @@ static struct blendinfo composite_op_info[] = { {1, 1, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, [PictOpAdd] = {0, 0, GL_ONE, GL_ONE}, }; - +#define RepeatFix 10 static GLuint glamor_create_composite_fs(glamor_gl_dispatch * dispatch, struct shader_key *key) @@ -75,6 +75,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "#define RepeatNormal 1\n" "#define RepeatPad 2\n" "#define RepeatReflect 3\n" + "#define RepeatFix 10\n" "uniform int source_repeat_mode;\n" "uniform int mask_repeat_mode;\n"; const char *relocate_texture = @@ -83,7 +84,9 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "{\n" " vec2 rel_tex; \n" " rel_tex = texture * wh; \n" - " if (repeat == RepeatNormal) \n" + " if (repeat == RepeatNone)\n" + " return rel_tex; \n" + " else if (repeat == RepeatNormal) \n" " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n" " else if(repeat == RepeatPad) { \n" " if (rel_tex.x > 1.0) rel_tex.x = 1.0; \n" @@ -104,6 +107,24 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, " } \n" " return rel_tex; \n" "}\n"; + /* The texture and the pixmap size is not match eaxctly, so can't sample it directly. + * rel_sampler will recalculate the texture coords.*/ + const char *rel_sampler = + " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec2 wh, int repeat, int set_alpha)\n" + "{\n" + " tex = rel_tex_coord(tex, wh, repeat - RepeatFix);\n" + " if (repeat == RepeatFix) {\n" + " if (!(tex.x >= 0.0 && tex.x <= 1.0 \n" + " && tex.y >= 0.0 && tex.y <= 1.0))\n" + " return vec4(0.0, 0.0, 0.0, set_alpha);\n" + " tex = (fract(tex) / wh);\n" + " }\n" + " if (set_alpha != 1)\n" + " return texture2D(tex_image, tex);\n" + " else\n" + " return vec4(texture2D(tex_image, tex).rgb, 1.0);\n" + "}\n"; + const char *source_solid_fetch = GLAMOR_DEFAULT_PRECISION "uniform vec4 source;\n" @@ -115,12 +136,11 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 source_wh;" "vec4 get_source()\n" "{\n" - " if (source_repeat_mode == RepeatNone) \n" + " if (source_repeat_mode < RepeatFix)\n" " return texture2D(source_sampler, source_texture);\n" - " else \n" - " return texture2D(source_sampler,\n" - " rel_tex_coord(source_texture,\n" - " source_wh, source_repeat_mode));\n" + " else \n" + " return rel_sampler(source_sampler, source_texture,\n" + " source_wh, source_repeat_mode, 0);\n" "}\n"; const char *source_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" @@ -128,12 +148,11 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 source_wh;\n" "vec4 get_source()\n" "{\n" - " if (source_repeat_mode == RepeatNone) \n" + " if (source_repeat_mode < RepeatFix) \n" " return vec4(texture2D(source_sampler, source_texture).rgb, 1);\n" " else \n" - " return vec4(texture2D(source_sampler, \n" - " rel_tex_coord(source_texture,\n" - " source_wh, source_repeat_mode)).rgb, 1);\n" + " return rel_sampler(source_sampler, source_texture,\n" + " source_wh, source_repeat_mode, 1);\n" "}\n"; const char *mask_solid_fetch = GLAMOR_DEFAULT_PRECISION "uniform vec4 mask;\n" @@ -144,12 +163,11 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 mask_wh;\n" "vec4 get_mask()\n" "{\n" - " if (mask_repeat_mode == RepeatNone) \n" + " if (mask_repeat_mode < RepeatFix) \n" " return texture2D(mask_sampler, mask_texture);\n" " else \n" - " return texture2D(mask_sampler, \n" - " rel_tex_coord(mask_texture, \n" - " mask_wh, mask_repeat_mode));\n" + " return rel_sampler(mask_sampler, mask_texture,\n" + " mask_wh, mask_repeat_mode, 0);\n" "}\n"; const char *mask_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" @@ -157,12 +175,11 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform vec2 mask_wh;\n" "vec4 get_mask()\n" "{\n" - " if (mask_repeat_mode == RepeatNone) \n" + " if (mask_repeat_mode < RepeatFix) \n" " return vec4(texture2D(mask_sampler, mask_texture).rgb, 1);\n" " else \n" - " return vec4(texture2D(mask_sampler, \n" - " rel_tex_coord(mask_texture, \n" - " mask_wh, mask_repeat_mode)).rgb, 1);\n" + " return rel_sampler(mask_sampler, mask_texture,\n" + " mask_wh, mask_repeat_mode, 1);\n" "}\n"; const char *in_source_only = GLAMOR_DEFAULT_PRECISION "void main()\n" "{\n" @@ -229,7 +246,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, FatalError("Bad composite IN type"); } - XNFasprintf(&source, "%s%s%s%s%s", repeat_define, relocate_texture, source_fetch, mask_fetch, in); + XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture, rel_sampler,source_fetch, mask_fetch, in); prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, @@ -524,11 +541,12 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, glamor_gl_dispatch *dispatch; float wh[2]; Bool has_repeat; + int repeat_type; dispatch = glamor_get_dispatch(glamor_priv); dispatch->glActiveTexture(GL_TEXTURE0 + unit); dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); - + repeat_type = picture->repeatType; switch (picture->repeatType) { case RepeatNone: #ifndef GLAMOR_GLES2 @@ -537,6 +555,11 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, GL_CLAMP_TO_BORDER); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); +#else + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); #endif break; case RepeatNormal: @@ -560,6 +583,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, } switch (picture->filter) { + default: case PictFilterNearest: dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -569,7 +593,6 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, GL_NEAREST); break; case PictFilterBilinear: - default: dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -581,14 +604,22 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - dispatch->glUniform1i(repeat_location, picture->repeatType); - if (picture->repeatType != RepeatNone) { - wh[0] = (float)pixmap_priv->fbo->width - / pixmap_priv->container->drawable.width; - wh[1] = (float)pixmap_priv->fbo->height - / pixmap_priv->container->drawable.height; + /* XXX may be we can eaxctly check whether we need to touch + * the out-of-box area then determine whether we need to fix. + * */ + if (repeat_type != RepeatNone) + repeat_type += RepeatFix; + else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { + if (picture->transform + || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + repeat_type += RepeatFix; + } + + if (repeat_type >= RepeatFix) { + glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); dispatch->glUniform2fv(wh_location, 1, wh); } + dispatch->glUniform1i(repeat_location, repeat_type); glamor_put_dispatch(glamor_priv); } @@ -694,6 +725,7 @@ glamor_composite_with_copy(CARD8 op, if (region.extents.y2 + y_source - y_dest > source->pDrawable->height) goto cleanup_region; } + ret = glamor_copy_n_to_n_nf(source->pDrawable, dest->pDrawable, NULL, REGION_RECTS(®ion), diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index c46849090..f39e3a532 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -18,6 +18,17 @@ *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height; \ } while(0) +#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv) \ + (priv->fbo->width != priv->container->drawable.width \ + || priv->fbo->height != priv->container->drawable.height) + +#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv) do { \ + wh[0] = (float)priv->fbo->width \ + / priv->container->drawable.width; \ + wh[1] = (float)priv->fbo->height \ + / priv->container->drawable.height; \ + } while(0) + #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \ + ((float)xFixedFrac(_val_) / 65536.0)) From 503f8ec1a670e73f41314a5e94cdde8782d7cbab Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 13:42:48 +0800 Subject: [PATCH 365/462] Remove unecessary header file. Signed-off-by: Zhigang Gong --- glamor/glamor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor.h b/glamor/glamor.h index c608ed855..e6206d09e 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -33,7 +33,6 @@ #include #endif #include -#include #include #include #include From 0d846d95699fadcddcc77b8d6e432e969467dab2 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 13:43:39 +0800 Subject: [PATCH 366/462] Added --enable-debug configuration option. For release version, we disable asserts. Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 3 ++- glamor/glamor_priv.h | 4 +++- glamor/glamor_render.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 081b363ab..c2627b9ce 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -287,7 +287,8 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Couldn't flink pixmap handle\n"); glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); - exit(1); + assert(0); + return FALSE; } } else name = handle; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 2aa03d005..91473c32d 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -32,7 +32,9 @@ #endif #include - +#ifndef DEBUG +#define NDEBUG +#endif #include "glamor.h" #define GL_GLEXT_PROTOTYPES diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index de01aab33..3f3a3bc18 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -427,7 +427,7 @@ glamor_init_composite_shaders(ScreenPtr screen) } if (eb == NULL) - FatalError("fatal error, fail to get eb.\n"); + FatalError("fatal error, fail to get element buffer. GL context may be not created correctly.\n"); glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { From 5c1f15fac26b86b6cb73776db1a644d6af570da7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 14:13:47 +0800 Subject: [PATCH 367/462] Added some copyright and author information. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 + glamor/glamor.h | 1 + glamor/glamor_copyarea.c | 5 ++++- glamor/glamor_debug.h | 28 ++++++++++++++++++++++++++++ glamor/glamor_eglmodule.c | 3 +++ glamor/glamor_fbo.c | 28 ++++++++++++++++++++++++++++ glamor/glamor_fill.c | 4 ++++ glamor/glamor_getspans.c | 1 + glamor/glamor_gl_dispatch.c | 28 ++++++++++++++++++++++++++++ glamor/glamor_glext.h | 29 +++++++++++++++++++++++++++++ glamor/glamor_picture.c | 28 ++++++++++++++++++++++++++++ glamor/glamor_pixmap.c | 29 +++++++++++++++++++++++++++++ glamor/glamor_putimage.c | 1 + glamor/glamor_render.c | 2 ++ glamor/glamor_setspans.c | 1 + glamor/glamor_tile.c | 1 + glamor/glamor_utils.h | 27 +++++++++++++++++++++++++++ 17 files changed, 216 insertions(+), 1 deletion(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index ea822f318..f924c91db 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Zhigang Gong * */ diff --git a/glamor/glamor.h b/glamor/glamor.h index e6206d09e..da45acc89 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Zhigang Gong * */ diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index f28206791..ee9e9f44a 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -19,6 +19,10 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Eric Anholt + * Zhigang Gong */ #include "glamor_priv.h" @@ -329,7 +333,6 @@ _glamor_copy_n_to_n(DrawablePtr src, } } } - /* XXX need revisit to handle overlapped area copying. */ #ifndef GLAMOR_GLES2 if ((overlaped || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex) diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h index ac7e69870..99dce041c 100644 --- a/glamor/glamor_debug.h +++ b/glamor/glamor_debug.h @@ -1,3 +1,31 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + #ifndef __GLAMOR_DEBUG_H__ #define __GLAMOR_DEBUG_H__ diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c index 096165162..046f4de5b 100644 --- a/glamor/glamor_eglmodule.c +++ b/glamor/glamor_eglmodule.c @@ -22,6 +22,9 @@ * not be used in advertising or otherwise to promote the sale, use or other * dealings in this Software without prior written authorization from the * XFree86 Project. + * + * Authors: + * Zhigang Gong */ #ifdef HAVE_CONFIG_H diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index a7cae664d..9b8dcdf5e 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -1,3 +1,31 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + #include #include "glamor_priv.h" diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 95b070db0..def4550c0 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -19,6 +19,10 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Eric Anholt + * Zhigang Gong */ #include "glamor_priv.h" diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c index 22e2b7c6b..6d6c8e9a4 100644 --- a/glamor/glamor_getspans.c +++ b/glamor/glamor_getspans.c @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Zhigang Gong * */ diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index e6da94d9c..f99650425 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -1,3 +1,31 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + #include "glamor_priv.h" #include diff --git a/glamor/glamor_glext.h b/glamor/glamor_glext.h index f734d1313..d60c69690 100644 --- a/glamor/glamor_glext.h +++ b/glamor/glamor_glext.h @@ -1,3 +1,32 @@ +/* + * Copyright © 2001 Keith Packard + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + + #ifdef GLAMOR_GLES2 #define GL_BGRA GL_BGRA_EXT diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 38185a491..a6d21f110 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -1,3 +1,31 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1998 Keith Packard + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + #include #include "glamor_priv.h" diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 68a7b0638..5c46b0355 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -1,3 +1,32 @@ +/* + * Copyright © 2001 Keith Packard + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * Zhigang Gong + * + */ + #include #include "glamor_priv.h" diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 0c3c0c5ba..a1119b65c 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Zhigang Gong * */ diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 3f3a3bc18..0377a8a00 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -22,6 +22,8 @@ * * Authors: * Eric Anholt + * Zhigang Gong + * Junyan He * */ diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index e28385335..a71efe901 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Zhigang Gong * */ diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 8e0955364..df66d05ec 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Zhigang Gong * */ diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index f39e3a532..d133135af 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -1,3 +1,30 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + */ + #ifndef GLAMOR_PRIV_H #error This file can only be included by glamor_priv.h #endif From c0f75c657f36642faea4ff8c51f7e4f6971c3d19 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 14:51:27 +0800 Subject: [PATCH 368/462] Fixed one typo bug when fixup a mask picture. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 0377a8a00..c6f9c0634 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -403,9 +403,8 @@ glamor_init_composite_shaders(ScreenPtr screen) glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; unsigned short *eb; - float *vb; + float *vb = NULL; int eb_size; - int vb_size; glamor_priv = glamor_get_screen_private(screen); dispatch = glamor_get_dispatch(glamor_priv); @@ -542,7 +541,6 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; float wh[2]; - Bool has_repeat; int repeat_type; dispatch = glamor_get_dispatch(glamor_priv); @@ -1163,7 +1161,7 @@ glamor_composite_with_shader(CARD8 op, if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) goto fail; } - if (key.mask != SHADER_SOURCE_SOLID && key.mask != SHADER_MASK_SOLID + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID && mask->transform && !pixman_transform_is_int_translate(mask->transform)) { if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) @@ -1341,6 +1339,7 @@ done: return ret; } +#ifdef GLAMOR_GRADIENT_SHADER static GLint _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_array) { @@ -1348,7 +1347,6 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar glamor_gl_dispatch *dispatch; char *gradient_fs = NULL; - GLint gradient_prog = 0; GLint fs_getcolor_prog; const char *gradient_fs_getcolor = @@ -2252,7 +2250,6 @@ _glamor_generate_radial_gradient_picture(ScreenPtr screen, glamor_gl_dispatch *dispatch; PicturePtr dst_picture = NULL; PixmapPtr pixmap = NULL; - glamor_pixmap_private *pixmap_priv; GLint gradient_prog = 0; int error; float tex_vertices[8]; @@ -2581,7 +2578,6 @@ _glamor_generate_linear_gradient_picture(ScreenPtr screen, int stops_count; GLfloat *stop_colors = NULL; GLfloat *n_stops = NULL; - int i = 0; int count = 0; float slope; GLfloat xscale, yscale; @@ -2919,6 +2915,7 @@ GRADIENT_FAIL: return NULL; } #undef LINEAR_DEFAULT_STOPS +#endif static PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, @@ -3009,17 +3006,16 @@ _glamor_composite(CARD8 op, Bool ret = TRUE; RegionRec region; BoxPtr box; - int nbox, i, ok; + int nbox, i, ok = FALSE; PixmapPtr sub_dest_pixmap = NULL; PixmapPtr sub_source_pixmap = NULL; PixmapPtr sub_mask_pixmap = NULL; - int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y; - int source_x_off, source_y_off, saved_source_x, saved_source_y; - int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y; - DrawablePtr saved_dest_drawable; - DrawablePtr saved_source_drawable; - DrawablePtr saved_mask_drawable; - + int dest_x_off, dest_y_off, saved_dest_x = 0, saved_dest_y = 0; + int source_x_off, source_y_off, saved_source_x = 0, saved_source_y = 0; + int mask_x_off, mask_y_off, saved_mask_x = 0, saved_mask_y = 0; + DrawablePtr saved_dest_drawable = NULL; + DrawablePtr saved_source_drawable = NULL; + DrawablePtr saved_mask_drawable = NULL; x_temp_src = x_source; y_temp_src = y_source; From 33e11cd6149294060269ed693de67b135868e094 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 14:54:38 +0800 Subject: [PATCH 369/462] Fixed an uninitialized problem at gradient shader functions. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index c6f9c0634..b729e986d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1651,6 +1651,8 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dy return; } + dispatch = glamor_get_dispatch(glamor_priv); + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) { dispatch->glDeleteShader( glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); @@ -1668,8 +1670,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dy glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0; } - dispatch = glamor_get_dispatch(glamor_priv); - gradient_prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(dispatch, @@ -1883,6 +1883,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy return; } + dispatch = glamor_get_dispatch(glamor_priv); if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) { dispatch->glDeleteShader( glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); @@ -1900,8 +1901,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0; } - dispatch = glamor_get_dispatch(glamor_priv); - gradient_prog = dispatch->glCreateProgram(); vs_prog = glamor_compile_glsl_prog(dispatch, From 1035fc72b9017eb2466760133ca7bbc9155c8c46 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 14:55:34 +0800 Subject: [PATCH 370/462] Fixed all unused variables warnings. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 3 --- glamor/glamor_copyarea.c | 3 +-- glamor/glamor_egl.c | 3 +-- glamor/glamor_fbo.c | 6 +----- glamor/glamor_fill.c | 4 +--- glamor/glamor_getimage.c | 1 - glamor/glamor_glyphblt.c | 4 ---- glamor/glamor_pixmap.c | 27 +++++++++------------------ glamor/glamor_polyfillrect.c | 1 - glamor/glamor_priv.h | 3 +-- glamor/glamor_putimage.c | 1 - glamor/glamor_utils.h | 2 -- 12 files changed, 14 insertions(+), 44 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index f924c91db..87c983944 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -136,7 +136,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_get_screen_private(screen); glamor_pixmap_fbo *fbo; int pitch; - int flag; GLenum format; if (w > 32767 || h > 32767) @@ -463,8 +462,6 @@ glamor_close_screen(int idx, ScreenPtr screen) { glamor_screen_private *glamor_priv; PixmapPtr screen_pixmap; - glamor_pixmap_private *screen_pixmap_priv; - glamor_pixmap_fbo *fbo; int flags; glamor_priv = glamor_get_screen_private(screen); diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index ee9e9f44a..3bb077cee 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -398,8 +398,7 @@ _glamor_copy_n_to_n(DrawablePtr src, if (src_pixmap_priv->type == GLAMOR_DRM_ONLY || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) { LogMessage(X_WARNING, - "Access a DRM only pixmap is not allowed within glamor.\n", - dst->pScreen->myNum); + "Access a DRM only pixmap is not allowed within glamor.\n"); return TRUE; } glamor_report_delayed_fallbacks(src->pScreen); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index c2627b9ce..35bcc9e68 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -260,10 +260,9 @@ glamor_egl_check_has_gem(int fd) { struct drm_gem_flink flink; flink.handle = 0; - int err; ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - if (errno == ENOENT || err == EINVAL) + if (errno == ENOENT || errno == EINVAL) return TRUE; return FALSE; } diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 9b8dcdf5e..d80771a14 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -98,7 +98,6 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, { struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry, *ret_fbo = NULL; - int size; int n_format; #ifdef NO_FBO_CACHE return NULL; @@ -436,7 +435,7 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format) { glamor_gl_dispatch *dispatch; - int tex; + unsigned int tex; dispatch = glamor_get_dispatch(glamor_priv); dispatch->glGenTextures(1, &tex); @@ -451,15 +450,12 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, return tex; } - - glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag) { - glamor_gl_dispatch *dispatch; glamor_pixmap_fbo *fbo; GLint tex = 0; int cache_flag; diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index def4550c0..072408e80 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -40,7 +40,7 @@ glamor_fill(DrawablePtr drawable, PixmapPtr sub_pixmap = NULL; glamor_access_t sub_pixmap_access; DrawablePtr saved_drawable = NULL; - int saved_x, saved_y; + int saved_x = x, saved_y = y; glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y); @@ -119,8 +119,6 @@ glamor_fill(DrawablePtr drawable, } if (sub_pixmap != NULL) { - struct pixman_box16 box; - int dx, dy; if (gc->fillStyle != FillSolid) { gc->patOrg.x -= (saved_drawable->x - saved_x); gc->patOrg.y -= (saved_drawable->y - saved_y); diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index b53635c5c..655ed94ee 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -37,7 +37,6 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, PixmapPtr pixmap, sub_pixmap; struct glamor_pixmap_private *pixmap_priv; int x_off, y_off; - Bool ret = FALSE; int stride; void *data; diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c index 18ad536eb..b55327c4b 100644 --- a/glamor/glamor_glyphblt.c +++ b/glamor/glamor_glyphblt.c @@ -33,8 +33,6 @@ _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) { - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) @@ -65,8 +63,6 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase, Bool fallback) { - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable) && glamor_ddx_fallback_check_gc(pGC)) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 5c46b0355..9b40b6635 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -188,7 +188,6 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) void * _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int stride, int revert) { - void *bits; PictFormatShort dst_format, src_format; pixman_image_t *dst_image; pixman_image_t *src_image; @@ -209,7 +208,6 @@ _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int st dst_bits, stride); if (dst_image == NULL) { - free(bits); return NULL; } @@ -220,7 +218,6 @@ _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int st if (src_image == NULL) { pixman_image_unref(dst_image); - free(bits); return NULL; } @@ -384,7 +381,7 @@ glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, int s **/ int in_restore = 0; static void -__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, int *tex, +__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, GLenum format, GLenum type, int x, int y, int w, int h, @@ -394,7 +391,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, int *tex, glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; int non_sub = 0; - int iformat; + unsigned int iformat = 0; dispatch = glamor_get_dispatch(glamor_priv); if (*tex == 0) { @@ -480,7 +477,8 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty stride, no_alpha, revert, swap_rb); if (bits == NULL) { - ErrorF("Failed to convert pixmap no_alpha %d, revert mode %d, swap mode %d\n", swap_rb); + ErrorF("Failed to convert pixmap no_alpha %d," + "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb); return FALSE; } no_alpha = 0; @@ -698,8 +696,7 @@ void glamor_restore_pixmap_to_texture(PixmapPtr pixmap) { if (glamor_upload_pixmap_to_texture(pixmap) != GLAMOR_UPLOAD_DONE) - LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n", - pixmap->drawable.pScreen->myNum); + LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n"); } /* @@ -800,7 +797,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, int stride, void *bits, int pbo, glamor_access_t access) { glamor_pixmap_private *pixmap_priv; - GLenum format, type, gl_access, gl_usage; + GLenum format, type, gl_access = 0, gl_usage = 0; int no_alpha, revert, swap_rb; void *data, *read; ScreenPtr screen; @@ -904,7 +901,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); } } else { - int temp_pbo; + unsigned int temp_pbo; int yy; dispatch = glamor_get_dispatch(glamor_priv); @@ -940,8 +937,6 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, revert, swap_rb); } - done: - if (temp_fbo != NULL) glamor_destroy_fbo(temp_fbo); if (need_free_data) @@ -965,9 +960,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - unsigned int stride, y; - GLenum format, type, gl_access, gl_usage; - int no_alpha, revert, swap_rb; + unsigned int stride; void *data = NULL, *dst; ScreenPtr screen; glamor_screen_private *glamor_priv = @@ -1024,8 +1017,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; - done: - pixmap->devPrivate.ptr = dst; return TRUE; @@ -1188,7 +1179,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces return sub_pixmap; } -PixmapPtr +void glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access) { void *bits; diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index bbe10a1b1..738e8eb11 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -44,7 +44,6 @@ _glamor_poly_fill_rect(DrawablePtr drawable, RegionPtr pClip = fbGetCompositeClip(gc); Bool ret = FALSE; glamor_screen_private *glamor_priv; - xRectangle *saved_prect = prect; glamor_priv = glamor_get_screen_private(drawable->pScreen); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 91473c32d..ca88fb4a4 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -648,8 +648,7 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h PixmapPtr glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access); - -PixmapPtr +void glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access); diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index a1119b65c..d1e3a83a1 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -255,7 +255,6 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_get_pixmap_private(pixmap); RegionPtr clip; int x_off, y_off; - float vertices[8], texcoords[8]; Bool ret = FALSE; PixmapPtr temp_pixmap, sub_pixmap; glamor_pixmap_private *temp_pixmap_priv; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index d133135af..9d32e6e11 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -1018,8 +1018,6 @@ static inline void glamor_compare_pictures( ScreenPtr screen, PixmapPtr fst_pixmap; PixmapPtr snd_pixmap; int fst_generated, snd_generated; - glamor_pixmap_private *fst_pixmap_priv; - glamor_pixmap_private *snd_pixmap_priv; int error; int fst_type = -1; int snd_type = -1; // -1 represent has drawable. From 6839996b0b0fe5f4e6ef28d1dfe527092d60d28a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 28 Apr 2012 18:23:09 +0800 Subject: [PATCH 371/462] We should not call gradient finalization code if we disable it. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index 87c983944..691f758e9 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -427,7 +427,9 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_fini_tile_shader(screen); glamor_fini_putimage_shaders(screen); glamor_fini_finish_access_shaders(screen); +#ifdef GLAMOR_GRADIENT_SHADER glamor_fini_gradient_shader(screen); +#endif glamor_pixmap_fini(screen); free(glamor_priv); From c5b3c2cedc8b2e486b1e3727f288c42869310387 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 15 May 2012 10:42:41 +0800 Subject: [PATCH 372/462] Added strict warning flags to CFLAGS. We miss the strict warning flags for a long time, now add it back. This commit also fixed most of the warnings after enable the strict flags. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 2 +- glamor/glamor.c | 5 ++--- glamor/glamor.h | 3 +++ glamor/glamor_egl.c | 19 +++++++++---------- glamor/glamor_fbo.c | 8 ++++---- glamor/glamor_pixmap.c | 12 ++++++------ glamor/glamor_render.c | 2 +- glamor/glamor_utils.h | 2 +- glamor/glapi.h | 6 +++--- 9 files changed, 30 insertions(+), 29 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index c7e300096..8e334b15e 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -15,7 +15,7 @@ instdir = $(moduledir) INCLUDES = \ $(XORG_INCS) -AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) +AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) libglamor_la_LDFLAGS = -avoid-version diff --git a/glamor/glamor.c b/glamor/glamor.c index 691f758e9..6b6fa0bec 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -465,12 +465,11 @@ glamor_close_screen(int idx, ScreenPtr screen) glamor_screen_private *glamor_priv; PixmapPtr screen_pixmap; int flags; - - glamor_priv = glamor_get_screen_private(screen); - flags = glamor_priv->flags; #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif + glamor_priv = glamor_get_screen_private(screen); + flags = glamor_priv->flags; glamor_glyphs_fini(screen); screen->CloseScreen = glamor_priv->saved_procs.close_screen; if (flags & GLAMOR_USE_SCREEN) { diff --git a/glamor/glamor.h b/glamor/glamor.h index da45acc89..c2db86a3a 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -157,6 +157,9 @@ extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen); * */ extern _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back); +extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back); + + #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 35bcc9e68..07acf1a37 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -91,7 +91,8 @@ struct glamor_egl_screen_private { struct gbm_device *gbm; #endif int has_gem; - void *gl_context, *old_context; + void *glamor_context; + void *current_context; int gl_context_depth; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; @@ -121,10 +122,9 @@ glamor_egl_make_current(ScreenPtr screen) if (glamor_egl->gl_context_depth++) return; - GET_CURRENT_CONTEXT(current); - glamor_egl->old_context = current; + GET_CURRENT_CONTEXT(glamor_egl->current_context); - if (glamor_egl->gl_context != current) { + if (glamor_egl->glamor_context != glamor_egl->current_context) { eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!eglMakeCurrent(glamor_egl->display, @@ -145,9 +145,9 @@ glamor_egl_restore_context(ScreenPtr screen) if (--glamor_egl->gl_context_depth) return; - if (glamor_egl->old_context && - glamor_egl->gl_context != glamor_egl->old_context) - SET_CURRENT_CONTEXT(glamor_egl->old_context); + if (glamor_egl->current_context && + glamor_egl->glamor_context != glamor_egl->current_context) + SET_CURRENT_CONTEXT(glamor_egl->current_context); } #else #define glamor_egl_make_current(x) @@ -255,7 +255,7 @@ glamor_egl_create_textured_screen_ext(ScreenPtr screen, return TRUE; } -Bool +static Bool glamor_egl_check_has_gem(int fd) { struct drm_gem_flink flink; @@ -548,8 +548,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) return FALSE; } #ifdef GLX_USE_SHARED_DISPATCH - GET_CURRENT_CONTEXT(current); - glamor_egl->gl_context = current; + GET_CURRENT_CONTEXT(glamor_egl->glamor_context); #endif glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index d80771a14..546fe7b35 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -92,7 +92,7 @@ inline static int cache_hbucket(int size) return order; } -glamor_pixmap_fbo * +static glamor_pixmap_fbo * glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag) { @@ -380,7 +380,7 @@ glamor_destroy_fbo(glamor_pixmap_fbo *fbo) } -glamor_pixmap_fbo * +static glamor_pixmap_fbo * glamor_create_tex_obj(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag) { @@ -422,7 +422,7 @@ glamor_create_tex_obj(glamor_screen_private *glamor_priv, return fbo; } -void +static void glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) { assert(tex_obj->fb == 0); @@ -430,7 +430,7 @@ glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) glamor_pixmap_fbo_cache_put(tex_obj); } -int +static int _glamor_create_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format) { diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 9b40b6635..3f268d989 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -185,7 +185,7 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) return TRUE; } -void * +static void * _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int stride, int revert) { PictFormatShort dst_format, src_format; @@ -269,7 +269,7 @@ _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h, int st (*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \ } -void * +static void * _glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) { int x,y; @@ -306,7 +306,7 @@ _glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h, i } -void * +static void * _glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) { int x,y; @@ -360,7 +360,7 @@ _glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h, int * */ -void * +static void * glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, int stride, int no_alpha, int revert, int swap_rb) { if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) { @@ -917,8 +917,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); for (yy = 0; yy < pixmap->drawable.height; yy++) - memcpy(data + yy * stride, - read + (h - yy - 1) * stride, stride); + memcpy((char*)data + yy * stride, + (char*)read + (h - yy - 1) * stride, stride); dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); dispatch->glDeleteBuffers(1, &temp_pbo); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b729e986d..a17b6fd21 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -961,11 +961,11 @@ glamor_composite_with_shader(CARD8 op, PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; GLfloat source_solid_color[4], mask_solid_color[4]; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); int vert_stride = 4; int nrect_max; Bool ret = FALSE; + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 9d32e6e11..5cd37de4e 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -886,9 +886,9 @@ static inline void _glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2, int little_endian = 0; unsigned char *p_test; int bpp = pixmap1->drawable.depth == 8 ? 1 : 4; + int stride = pixmap1->devKind; assert(pixmap1->devKind == pixmap2->devKind); - int stride = pixmap1->devKind; ErrorF("stride:%d, width:%d, height:%d\n", stride, w, h); diff --git a/glamor/glapi.h b/glamor/glapi.h index da521aa7c..d510dac1d 100644 --- a/glamor/glapi.h +++ b/glamor/glapi.h @@ -79,7 +79,7 @@ extern const struct _glapi_table *_glapi_Dispatch; extern const void *_glapi_Context; # define GET_DISPATCH() _glapi_tls_Dispatch -# define GET_CURRENT_CONTEXT(C) struct gl_context *C = (struct gl_context *) _glapi_tls_Context +# define GET_CURRENT_CONTEXT(C) C = (typeof(C)) _glapi_tls_Context # define SET_CURRENT_CONTEXT(C) _glapi_tls_Context = (void*)C #else @@ -92,7 +92,7 @@ extern void *_glapi_Context; # define GET_DISPATCH() \ (likely(_glapi_Dispatch) ? _glapi_Dispatch : _glapi_get_dispatch()) -# define GET_CURRENT_CONTEXT(C) struct gl_context *C = (struct gl_context *) \ +# define GET_CURRENT_CONTEXT(C) C = (typeof(C)) \ (likely(_glapi_Context) ? _glapi_Context : _glapi_get_context()) @@ -104,7 +104,7 @@ extern void *_glapi_Context; # else # define GET_DISPATCH() _glapi_Dispatch -# define GET_CURRENT_CONTEXT(C) struct gl_context *C = (struct gl_context *) _glapi_Context +# define GET_CURRENT_CONTEXT(C) C = (typeof(C)) _glapi_Context # define SET_CURRENT_CONTEXT(C) _glapi_Context = (void*)C # endif From 7f55e48499ea7bed73cb1adeac00c480263583f8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 15 May 2012 10:52:37 +0800 Subject: [PATCH 373/462] Remove the texture cache code. Caching texture objects is not necessary based on previous testing. To keep the code simple, we remove it. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 94 +++----------------------------------------- glamor/glamor_priv.h | 1 - 2 files changed, 6 insertions(+), 89 deletions(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 546fe7b35..f4e02b205 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -34,7 +34,6 @@ #define GLAMOR_CACHE_DEFAULT 0 #define GLAMOR_CACHE_EXACT_SIZE 1 -#define GLAMOR_CACHE_TEXTURE 2 //#define NO_FBO_CACHE 1 #define FBO_CACHE_THRESHOLD (256*1024*1024) @@ -105,14 +104,9 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, n_format = cache_format(format); if (n_format == -1) return NULL; - if (!(flag & GLAMOR_CACHE_TEXTURE)) - cache = &glamor_priv->fbo_cache[n_format] - [cache_wbucket(w)] - [cache_hbucket(h)]; - else - cache = &glamor_priv->tex_cache[n_format] - [cache_wbucket(w)] - [cache_hbucket(h)]; + cache = &glamor_priv->fbo_cache[n_format] + [cache_wbucket(w)] + [cache_hbucket(h)]; if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) { xorg_list_for_each_entry(fbo_entry, cache, list) { if (fbo_entry->width >= w && fbo_entry->height >= h) { @@ -186,14 +180,9 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) return; } - if (fbo->fb) - cache = &fbo->glamor_priv->fbo_cache[n_format] - [cache_wbucket(fbo->width)] - [cache_hbucket(fbo->height)]; - else - cache = &fbo->glamor_priv->tex_cache[n_format] - [cache_wbucket(fbo->width)] - [cache_hbucket(fbo->height)]; + cache = &fbo->glamor_priv->fbo_cache[n_format] + [cache_wbucket(fbo->width)] + [cache_hbucket(fbo->height)]; DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, fbo->width, fbo->height, fbo->format, fbo->fb, fbo->tex); @@ -310,19 +299,6 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) fbo_entry->expire, glamor_priv->tick); glamor_purge_fbo(fbo_entry); } -#if 0 - cache = &glamor_priv->tex_cache[i][j][k]; - xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { - if (GLAMOR_TICK_AFTER(fbo_entry->expire, glamor_priv->tick)) { - empty_cache = FALSE; - break; - } - xorg_list_del(&fbo_entry->list); - DEBUGF("cache %p fbo %p expired %d current %d \n", cache, fbo_entry, - fbo_entry->expire, glamor_priv->tick); - glamor_purge_fbo(fbo_entry); - } -#endif } } @@ -339,7 +315,6 @@ glamor_init_pixmap_fbo(ScreenPtr screen) for(k = 0; k < CACHE_BUCKET_HCOUNT; k++) { xorg_list_init(&glamor_priv->fbo_cache[i][j][k]); - xorg_list_init(&glamor_priv->tex_cache[i][j][k]); } glamor_priv->fbo_cache_watermark = 0; } @@ -362,13 +337,6 @@ glamor_fini_pixmap_fbo(ScreenPtr screen) xorg_list_del(&fbo_entry->list); glamor_purge_fbo(fbo_entry); } -#if 0 - cache = &glamor_priv->tex_cache[i][j][k]; - xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { - xorg_list_del(&fbo_entry->list); - glamor_purge_fbo(fbo_entry); - } -#endif } } @@ -380,56 +348,6 @@ glamor_destroy_fbo(glamor_pixmap_fbo *fbo) } -static glamor_pixmap_fbo * -glamor_create_tex_obj(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, int flag) -{ - glamor_gl_dispatch *dispatch; - glamor_pixmap_fbo *fbo; - int cache_flag = GLAMOR_CACHE_TEXTURE; - GLuint tex; - - if (flag == GLAMOR_CREATE_TEXTURE_EXACT_SIZE) - cache_flag |= GLAMOR_CACHE_EXACT_SIZE; - - fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, - format, cache_flag); - if (fbo) - return fbo; - fbo = calloc(1, sizeof(*fbo)); - if (fbo == NULL) - return NULL; - - xorg_list_init(&fbo->list); - - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glGenTextures(1, &tex); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, - GL_UNSIGNED_BYTE, NULL); - glamor_put_dispatch(glamor_priv); - - fbo->tex = tex; - fbo->width = w; - fbo->height = h; - fbo->format = format; - fbo->glamor_priv = glamor_priv; - - return fbo; -} - -static void -glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj) -{ - assert(tex_obj->fb == 0); - xorg_list_del(&tex_obj->list); - glamor_pixmap_fbo_cache_put(tex_obj); -} - static int _glamor_create_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index ca88fb4a4..d26f59f6e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -210,7 +210,6 @@ typedef struct glamor_screen_private { int max_fbo_size; struct xorg_list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; - struct xorg_list tex_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT]; unsigned long fbo_cache_watermark; /* glamor_solid */ From 81692804645394b43832c8ec586e8e67f3e4f606 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 15 May 2012 15:25:41 +0800 Subject: [PATCH 374/462] glamor_set_destination_pixmap_priv_nc: set drawable's width x height. Previous implementation set the whole fbo's width and height as the viewpoint. This may increase the numerical error as we may only has a partial region as the valid pixmap. So add a new marco pixmap_priv_get_dest_scale to get proper scale factor for the destination pixmap. For the source/mask pixmap, we still need to consider the whole fbo's size. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 4 +--- glamor/glamor_fill.c | 2 +- glamor/glamor_pixmap.c | 19 ++++++++++--------- glamor/glamor_priv.h | 2 +- glamor/glamor_render.c | 4 ++-- glamor/glamor_tile.c | 2 +- glamor/glamor_utils.h | 6 ++++++ 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 3bb077cee..356e0f9b6 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -183,7 +183,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, alu = gc->alu; } - pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, @@ -206,8 +206,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, &src_y_off); dx += src_x_off; dy += src_y_off; - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, - &src_yscale); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 072408e80..57dd69851 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -237,7 +237,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, GL_FALSE, 2 * sizeof(float), vertices); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); + pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 3f268d989..f0c158676 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -64,7 +64,7 @@ glamor_pixmap_fini(ScreenPtr screen) } void -glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo) +glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo, int x0, int y0, int width, int height) { glamor_gl_dispatch *dispatch = glamor_get_dispatch(fbo->glamor_priv); dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); @@ -74,9 +74,8 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo) dispatch->glMatrixMode(GL_MODELVIEW); dispatch->glLoadIdentity(); #endif - dispatch->glViewport(0, 0, - fbo->width, - fbo->height); + dispatch->glViewport(x0, y0, + width, height); glamor_put_dispatch(fbo->glamor_priv); } @@ -84,7 +83,9 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo) void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { - glamor_set_destination_pixmap_fbo(pixmap_priv->fbo); + glamor_set_destination_pixmap_fbo(pixmap_priv->fbo, 0, 0, + pixmap_priv->container->drawable.width, + pixmap_priv->container->drawable.height); } int @@ -507,7 +508,7 @@ ready_to_upload: else ptexcoords = texcoords_inv; - pixmap_priv_get_scale(pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale); glamor_set_normalize_vcoords(dst_xscale, dst_yscale, x, y, @@ -733,8 +734,8 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe return NULL; dispatch = glamor_get_dispatch(glamor_priv); - temp_xscale = 1.0 / temp_fbo->width; - temp_yscale = 1.0 / temp_fbo->height; + temp_xscale = 1.0 / w; + temp_yscale = 1.0 / h; glamor_set_normalize_vcoords(temp_xscale, temp_yscale, @@ -770,7 +771,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glamor_set_destination_pixmap_fbo(temp_fbo); + glamor_set_destination_pixmap_fbo(temp_fbo, 0, 0, w, h); dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUniform1i(glamor_priv-> finish_access_revert[no_alpha], diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index d26f59f6e..8f1d42876 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -456,7 +456,7 @@ void glamor_get_color_4f_from_pixel(PixmapPtr pixmap, int glamor_set_destination_pixmap(PixmapPtr pixmap); int glamor_set_destination_pixmap_priv(glamor_pixmap_private * pixmap_priv); -void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *); +void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *, int, int, int, int); /* nc means no check. caller must ensure this pixmap has valid fbo. * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly. diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index a17b6fd21..94f7dc5a5 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1210,7 +1210,7 @@ glamor_composite_with_shader(CARD8 op, glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, &dest_x_off, &dest_y_off); - pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); if (glamor_priv->has_source_coords) { glamor_get_drawable_deltas(source->pDrawable, @@ -2109,7 +2109,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, glamor_set_destination_pixmap_priv_nc(pixmap_priv); - pixmap_priv_get_scale(pixmap_priv, xscale, yscale); + pixmap_priv_get_dest_scale(pixmap_priv, xscale, yscale); glamor_priv->has_source_coords = 1; glamor_priv->has_mask_coords = 0; diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index df66d05ec..6790550a3 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -154,7 +154,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - pixmap_priv_get_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, alu)) { diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 5cd37de4e..8dad2dfd6 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -39,6 +39,12 @@ #define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_)) #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) +#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ + do { \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height; \ + } while(0) + #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width; \ From d900f553c2bb8d6e01529524fb7125918291c406 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 15 May 2012 10:07:24 +0800 Subject: [PATCH 375/462] Extract the gradient related code out. 1. Extract the logic of gradient from the glamor_render.c to the file glamor_gradient.c. 2. Modify the logic of gradient pixmap gl draw. Use the logic like composite before, but the gradient always just have one rect to render, so no need to set the VB and EB, replace it with just call glDrawArrays. 3.Kill all the warning in glamor_render.c Reviewed-by: Zhigang Gong Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor_gradient.c | 1633 ++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 13 +- glamor/glamor_render.c | 1587 +----------------------------------- 4 files changed, 1653 insertions(+), 1581 deletions(-) create mode 100644 glamor/glamor_gradient.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 8e334b15e..2e94ffd73 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -33,6 +33,7 @@ libglamor_la_SOURCES = \ glamor_putimage.c \ glamor_setspans.c \ glamor_render.c \ + glamor_gradient.c \ glamor_tile.c \ glamor_triangles.c\ glamor_addtraps.c\ diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c new file mode 100644 index 000000000..f1c36af69 --- /dev/null +++ b/glamor/glamor_gradient.c @@ -0,0 +1,1633 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Junyan He + * + */ + +/** @file glamor_gradient.c + * + * Gradient acceleration implementation + */ + +#include "glamor_priv.h" + +#ifdef RENDER + +#define LINEAR_SMALL_STOPS 6 + 2 +#define LINEAR_LARGE_STOPS 16 + 2 + +#define RADIAL_SMALL_STOPS 6 + 2 +#define RADIAL_LARGE_STOPS 16 + 2 + +#ifdef GLAMOR_GRADIENT_SHADER + +static GLint +_glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_array) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + char *gradient_fs = NULL; + GLint fs_getcolor_prog; + + const char *gradient_fs_getcolor = + GLAMOR_DEFAULT_PRECISION + "uniform int n_stop;\n" + "uniform float stops[%d];\n" + "uniform vec4 stop_colors[%d];\n" + "vec4 get_color(float stop_len)\n" + "{\n" + " int i = 0;\n" + " float new_alpha; \n" + " vec4 gradient_color;\n" + " float percentage; \n" + " for(i = 0; i < n_stop - 1; i++) {\n" + " if(stop_len < stops[i])\n" + " break; \n" + " }\n" + " \n" + " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n" + " if(stops[i] - stops[i-1] > 2.0)\n" + " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. + " new_alpha = percentage * stop_colors[i].a + \n" + " (1.0-percentage) * stop_colors[i-1].a; \n" + " gradient_color = vec4((percentage * stop_colors[i].rgb \n" + " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" + " return gradient_color;\n" + "}\n"; + + /* Because the array access for shader is very slow, the performance is very low + if use array. So use global uniform to replace for it if the number of n_stops is small.*/ + const char *gradient_fs_getcolor_no_array = + GLAMOR_DEFAULT_PRECISION + "uniform int n_stop;\n" + "uniform float stop0;\n" + "uniform float stop1;\n" + "uniform float stop2;\n" + "uniform float stop3;\n" + "uniform float stop4;\n" + "uniform float stop5;\n" + "uniform float stop6;\n" + "uniform float stop7;\n" + "uniform vec4 stop_color0;\n" + "uniform vec4 stop_color1;\n" + "uniform vec4 stop_color2;\n" + "uniform vec4 stop_color3;\n" + "uniform vec4 stop_color4;\n" + "uniform vec4 stop_color5;\n" + "uniform vec4 stop_color6;\n" + "uniform vec4 stop_color7;\n" + "\n" + "vec4 get_color(float stop_len)\n" + "{\n" + " float stop_after;\n" + " float stop_before;\n" + " vec4 stop_color_before;\n" + " vec4 stop_color_after;\n" + " float new_alpha; \n" + " vec4 gradient_color;\n" + " float percentage; \n" + " \n" + " if((stop_len < stop0) && (n_stop >= 1)) {\n" + " stop_color_before = stop_color0;\n" + " stop_color_after = stop_color0;\n" + " stop_after = stop0;\n" + " stop_before = stop0;\n" + " percentage = 0.0;\n" + " } else if((stop_len < stop1) && (n_stop >= 2)) {\n" + " stop_color_before = stop_color0;\n" + " stop_color_after = stop_color1;\n" + " stop_after = stop1;\n" + " stop_before = stop0;\n" + " percentage = (stop_len - stop0)/(stop1 - stop0);\n" + " } else if((stop_len < stop2) && (n_stop >= 3)) {\n" + " stop_color_before = stop_color1;\n" + " stop_color_after = stop_color2;\n" + " stop_after = stop2;\n" + " stop_before = stop1;\n" + " percentage = (stop_len - stop1)/(stop2 - stop1);\n" + " } else if((stop_len < stop3) && (n_stop >= 4)){\n" + " stop_color_before = stop_color2;\n" + " stop_color_after = stop_color3;\n" + " stop_after = stop3;\n" + " stop_before = stop2;\n" + " percentage = (stop_len - stop2)/(stop3 - stop2);\n" + " } else if((stop_len < stop4) && (n_stop >= 5)){\n" + " stop_color_before = stop_color3;\n" + " stop_color_after = stop_color4;\n" + " stop_after = stop4;\n" + " stop_before = stop3;\n" + " percentage = (stop_len - stop3)/(stop4 - stop3);\n" + " } else if((stop_len < stop5) && (n_stop >= 6)){\n" + " stop_color_before = stop_color4;\n" + " stop_color_after = stop_color5;\n" + " stop_after = stop5;\n" + " stop_before = stop4;\n" + " percentage = (stop_len - stop4)/(stop5 - stop4);\n" + " } else if((stop_len < stop6) && (n_stop >= 7)){\n" + " stop_color_before = stop_color5;\n" + " stop_color_after = stop_color6;\n" + " stop_after = stop6;\n" + " stop_before = stop5;\n" + " percentage = (stop_len - stop5)/(stop6 - stop5);\n" + " } else if((stop_len < stop7) && (n_stop >= 8)){\n" + " stop_color_before = stop_color6;\n" + " stop_color_after = stop_color7;\n" + " stop_after = stop7;\n" + " stop_before = stop6;\n" + " percentage = (stop_len - stop6)/(stop7 - stop6);\n" + " } else {\n" + " stop_color_before = stop_color7;\n" + " stop_color_after = stop_color7;\n" + " stop_after = stop7;\n" + " stop_before = stop7;\n" + " percentage = 0.0;\n" + " }\n" + " if(stop_after - stop_before > 2.0)\n" + " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. + " new_alpha = percentage * stop_color_after.a + \n" + " (1.0-percentage) * stop_color_before.a; \n" + " gradient_color = vec4((percentage * stop_color_after.rgb \n" + " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" + " new_alpha);\n" + " \n" + " return gradient_color;\n" + "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + if(use_array) { + XNFasprintf(&gradient_fs, + gradient_fs_getcolor, stops_count, stops_count); + fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + gradient_fs); + free(gradient_fs); + } else { + fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, + gradient_fs_getcolor_no_array); + } + + return fs_getcolor_prog; +} + +static void +_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + int index; + + GLint gradient_prog = 0; + char *gradient_fs = NULL; + GLint fs_main_prog, fs_getcolor_prog, vs_prog; + + const char *gradient_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" + "}\n"; + + /* + * Refer to pixman radial gradient. + * + * The problem is given the two circles of c1 and c2 with the radius of r1 and + * r1, we need to caculate the t, which is used to do interpolate with stops, + * using the fomula: + * length((1-t)*c1 + t*c2 - p) = (1-t)*r1 + t*r2 + * expand the fomula with xy coond, get the following: + * sqrt(sqr((1-t)*c1.x + t*c2.x - p.x) + sqr((1-t)*c1.y + t*c2.y - p.y)) + * = (1-t)r1 + t*r2 + * <====> At*t- 2Bt + C = 0 + * where A = sqr(c2.x - c1.x) + sqr(c2.y - c1.y) - sqr(r2 -r1) + * B = (p.x - c1.x)*(c2.x - c1.x) + (p.y - c1.y)*(c2.y - c1.y) + r1*(r2 -r1) + * C = sqr(p.x - c1.x) + sqr(p.y - c1.y) - r1*r1 + * + * solve the fomula and we get the result of + * t = (B + sqrt(B*B - A*C)) / A or + * t = (B - sqrt(B*B - A*C)) / A (quadratic equation have two solutions) + * + * The solution we are going to prefer is the bigger one, unless the + * radius associated to it is negative (or it falls outside the valid t range) + */ + + const char *gradient_fs_template = + GLAMOR_DEFAULT_PRECISION + "uniform mat3 transform_mat;\n" + "uniform int repeat_type;\n" + "uniform float A_value;\n" + "uniform vec2 c1;\n" + "uniform float r1;\n" + "uniform vec2 c2;\n" + "uniform float r2;\n" + "varying vec2 source_texture;\n" + "\n" + "vec4 get_color(float stop_len);\n" + "\n" + "int t_invalid;\n" + "\n" + "float get_stop_len()\n" + "{\n" + " float t = 0.0;\n" + " float sqrt_value;\n" + " int revserse = 0;\n" + " t_invalid = 0;\n" + " \n" + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" + " vec3 source_texture_trans = transform_mat * tmp;\n" + " source_texture_trans.xy = source_texture_trans.xy/source_texture_trans.z;\n" + " float B_value = (source_texture_trans.x - c1.x) * (c2.x - c1.x)\n" + " + (source_texture_trans.y - c1.y) * (c2.y - c1.y)\n" + " + r1 * (r2 - r1);\n" + " float C_value = (source_texture_trans.x - c1.x) * (source_texture_trans.x - c1.x)\n" + " + (source_texture_trans.y - c1.y) * (source_texture_trans.y - c1.y)\n" + " - r1*r1;\n" + " if(abs(A_value) < 0.00001) {\n" + " if(B_value == 0.0) {\n" + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " t = 0.5 * C_value / B_value;" + " } else {\n" + " sqrt_value = B_value * B_value - A_value * C_value;\n" + " if(sqrt_value < 0.0) {\n" + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " sqrt_value = sqrt(sqrt_value);\n" + " t = (B_value + sqrt_value) / A_value;\n" + " }\n" + " if(repeat_type == %d) {\n" // RepeatNone case. + " if((t <= 0.0) || (t > 1.0))\n" + // try another if first one invalid + " t = (B_value - sqrt_value) / A_value;\n" + " \n" + " if((t <= 0.0) || (t > 1.0)) {\n" //still invalid, return. + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " } else {\n" + " if(t * (r2 - r1) <= -1.0 * r1)\n" + // try another if first one invalid + " t = (B_value - sqrt_value) / A_value;\n" + " \n" + " if(t * (r2 -r1) <= -1.0 * r1) {\n" //still invalid, return. + " t_invalid = 1;\n" + " return t;\n" + " }\n" + " }\n" + " \n" + " if(repeat_type == %d){\n" // repeat normal + " while(t > 1.0) \n" + " t = t - 1.0; \n" + " while(t < 0.0) \n" + " t = t + 1.0; \n" + " }\n" + " \n" + " if(repeat_type == %d) {\n" // repeat reflect + " while(t > 1.0) {\n" + " t = t - 1.0; \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " while(t < 0.0) {\n" + " t = t + 1.0; \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " if(revserse == 1) {\n" + " t = 1.0 - t; \n" + " }\n" + " }\n" + " \n" + " return t;\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " float stop_len = get_stop_len();\n" + " if(t_invalid == 1) {\n" + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" + " } else {\n" + " gl_FragColor = get_color(stop_len);\n" + " }\n" + "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + + if ((glamor_priv->radial_max_nstops >= stops_count) && (dyn_gen)) { + /* Very Good, not to generate again. */ + return; + } + + dispatch = glamor_get_dispatch(glamor_priv); + + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) { + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; + + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]); + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0; + } + + gradient_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, + GL_VERTEX_SHADER, gradient_vs); + + XNFasprintf(&gradient_fs, + gradient_fs_template, + PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + + fs_main_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); + + free(gradient_fs); + + fs_getcolor_prog = + _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); + + dispatch->glAttachShader(gradient_prog, vs_prog); + dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); + dispatch->glAttachShader(gradient_prog, fs_main_prog); + + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_positionsition"); + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); + + glamor_link_glsl_prog(dispatch, gradient_prog); + + dispatch->glUseProgram(0); + + if (dyn_gen) { + index = 2; + glamor_priv->radial_max_nstops = stops_count; + } else if (stops_count) { + index = 1; + } else { + index = 0; + } + + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; + + glamor_put_dispatch(glamor_priv); +} + +static void +_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + int index = 0; + GLint gradient_prog = 0; + char *gradient_fs = NULL; + GLint fs_main_prog, fs_getcolor_prog, vs_prog; + + const char *gradient_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" + "}\n"; + + /* + * | + * |\ + * | \ + * | \ + * | \ + * |\ \ + * | \ \ + * cos_val = |\ p1d \ / + * sqrt(1/(slope*slope+1.0)) ------>\ \ \ / + * | \ \ \ + * | \ \ / \ + * | \ *Pt1\ + * *p1 | \ \ *P + * \ | / \ \ / + * \ | / \ \ / + * \ | pd \ + * \ | \ / \ + * p2* | \ / \ / + * slope = (p2.y - p1.y) / | / p2d / + * (p2.x - p1.x) | / \ / + * | / \ / + * | / / + * | / / + * | / *Pt2 + * | / + * | / + * | / + * | / + * | / + * -------+--------------------------------- + * O| + * | + * | + * + * step 1: compute the distance of p, pt1 and pt2 in the slope direction. + * Caculate the distance on Y axis first and multiply cos_val to + * get the value on slope direction(pd, p1d and p2d represent the + * distance of p, pt1, and pt2 respectively). + * + * step 2: caculate the percentage of (pd - p1d)/(p2d - p1d). + * If (pd - p1d) > (p2d - p1d) or < 0, then sub or add (p2d - p1d) + * to make it in the range of [0, (p2d - p1d)]. + * + * step 3: compare the percentage to every stop and find the stpos just + * before and after it. Use the interpolation fomula to compute RGBA. + */ + + const char *gradient_fs_template = + GLAMOR_DEFAULT_PRECISION + "uniform mat3 transform_mat;\n" + "uniform int repeat_type;\n" + "uniform int hor_ver;\n" + "uniform vec4 pt1;\n" + "uniform vec4 pt2;\n" + "uniform float pt_slope;\n" + "uniform float cos_val;\n" + "uniform float p1_distance;\n" + "uniform float pt_distance;\n" + "varying vec2 source_texture;\n" + "\n" + "vec4 get_color(float stop_len);\n" + "\n" + "float get_stop_len()\n" + "{\n" + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" + " float len_percentage;\n" + " float distance;\n" + " float _p1_distance;\n" + " float _pt_distance;\n" + " float y_dist;\n" + " float stop_after;\n" + " float stop_before;\n" + " vec4 stop_color_before;\n" + " vec4 stop_color_after;\n" + " float new_alpha; \n" + " int revserse = 0;\n" + " vec4 gradient_color;\n" + " float percentage; \n" + " vec3 source_texture_trans = transform_mat * tmp;\n" + " \n" + " if(hor_ver == 0) { \n" //Normal case. + " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n" + " distance = y_dist * cos_val;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " \n" + " } else if (hor_ver == 1) {\n"//horizontal case. + " distance = source_texture_trans.x;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " } else if (hor_ver == 2) {\n"//vertical case. + " distance = source_texture_trans.y;\n" + " _p1_distance = p1_distance * source_texture_trans.z;\n" + " _pt_distance = pt_distance * source_texture_trans.z;\n" + " } \n" + " \n" + " distance = distance - _p1_distance; \n" + " \n" + " if(repeat_type == %d){\n" // repeat normal + " while(distance > _pt_distance) \n" + " distance = distance - (_pt_distance); \n" + " while(distance < 0.0) \n" + " distance = distance + (_pt_distance); \n" + " }\n" + " \n" + " if(repeat_type == %d) {\n" // repeat reflect + " while(distance > _pt_distance) {\n" + " distance = distance - (_pt_distance); \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " while(distance < 0.0) {\n" + " distance = distance + (_pt_distance); \n" + " if(revserse == 0)\n" + " revserse = 1;\n" + " else\n" + " revserse = 0;\n" + " }\n" + " if(revserse == 1) {\n" + " distance = (_pt_distance) - distance; \n" + " }\n" + " }\n" + " \n" + " len_percentage = distance/(_pt_distance);\n" + " \n" + " return len_percentage;\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " float stop_len = get_stop_len();\n" + " gl_FragColor = get_color(stop_len);\n" + "}\n"; + + + glamor_priv = glamor_get_screen_private(screen); + + if ((glamor_priv->linear_max_nstops >= stops_count) && (dyn_gen)) { + /* Very Good, not to generate again. */ + return; + } + + dispatch = glamor_get_dispatch(glamor_priv); + if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) { + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; + + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; + + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]); + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0; + } + + gradient_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, + GL_VERTEX_SHADER, gradient_vs); + + XNFasprintf(&gradient_fs, + gradient_fs_template, + PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); + + fs_main_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, gradient_fs); + free(gradient_fs); + + fs_getcolor_prog = + _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); + + dispatch->glAttachShader(gradient_prog, vs_prog); + dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); + dispatch->glAttachShader(gradient_prog, fs_main_prog); + + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); + + glamor_link_glsl_prog(dispatch, gradient_prog); + + dispatch->glUseProgram(0); + + if (dyn_gen) { + index = 2; + glamor_priv->linear_max_nstops = stops_count; + } else if (stops_count) { + index = 1; + } else { + index = 0; + } + + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; + + glamor_put_dispatch(glamor_priv); +} + +void +glamor_init_gradient_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + int i; + + glamor_priv = glamor_get_screen_private(screen); + + for (i = 0; i < 3; i++) { + glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; + + glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; + } + glamor_priv->linear_max_nstops = 0; + glamor_priv->radial_max_nstops = 0; + + _glamor_create_linear_gradient_program(screen, 0, 0); + _glamor_create_linear_gradient_program(screen, LINEAR_LARGE_STOPS, 0); + + _glamor_create_radial_gradient_program(screen, 0, 0); + _glamor_create_radial_gradient_program(screen, RADIAL_LARGE_STOPS, 0); +} + +void +glamor_fini_gradient_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + int i = 0; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + for (i = 0; i < 3; i++) { + /* Linear Gradient */ + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); + + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); + + if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); + + if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]) + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]); + + /* Radial Gradient */ + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); + + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); + + if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) + dispatch->glDeleteShader( + glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); + + if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]) + dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]); + } + + glamor_put_dispatch(glamor_priv); +} + +static void +_glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], + int width, int height, int normalize) +{ + /* + * Because in the shader program, we normalize all the pixel cood to [0, 1], + * so with the transform matrix, the correct logic should be: + * v_s = A*T*v + * v_s: point vector in shader after normalized. + * A: The transition matrix from width X height --> 1.0 X 1.0 + * T: The transform matrix. + * v: point vector in width X height space. + * + * result is OK if we use this fomula. But for every point in width X height space, + * we can just use their normalized point vector in shader, namely we can just + * use the result of A*v in shader. So we have no chance to insert T in A*v. + * We can just convert v_s = A*T*v to v_s = A*T*inv(A)*A*v, where inv(A) is the + * inverse matrix of A. Now, v_s = (A*T*inv(A)) * (A*v) + * So, to get the correct v_s, we need to cacula1 the matrix: (A*T*inv(A)), and + * we name this matrix T_s. + * + * Firstly, because A is for the scale convertion, we find + * -- -- + * |1/w 0 0 | + * A = | 0 1/h 0 | + * | 0 0 1.0| + * -- -- + * so T_s = A*T*inv(a) and result + * + * -- -- + * | t11 h*t12/w t13/w| + * T_s = | w*t21/h t22 t23/h| + * | w*t31 h*t32 t33 | + * -- -- + */ + + to[0][0] = (float)pixman_fixed_to_double(from->matrix[0][0]); + to[0][1] = (float)pixman_fixed_to_double(from->matrix[0][1]) + * (normalize ? (((float)height) / ((float)width)) : 1.0); + to[0][2] = (float)pixman_fixed_to_double(from->matrix[0][2]) + / (normalize ? ((float)width) : 1.0); + + to[1][0] = (float)pixman_fixed_to_double(from->matrix[1][0]) + * (normalize ? (((float)width) / ((float)height)) : 1.0); + to[1][1] = (float)pixman_fixed_to_double(from->matrix[1][1]); + to[1][2] = (float)pixman_fixed_to_double(from->matrix[1][2]) + / (normalize ? ((float)height) : 1.0); + + to[2][0] = (float)pixman_fixed_to_double(from->matrix[2][0]) + * (normalize ? ((float)width) : 1.0); + to[2][1] = (float)pixman_fixed_to_double(from->matrix[2][1]) + * (normalize ? ((float)height) : 1.0); + to[2][2] = (float)pixman_fixed_to_double(from->matrix[2][2]); + + DEBUGF("the transform matrix is:\n%f\t%f\t%f\n%f\t%f\t%f\n%f\t%f\t%f\n", + to[0][0], to[0][1], to[0][2], + to[1][0], to[1][1], to[1][2], + to[2][0], to[2][1], to[2][2]); +} + +static int +_glamor_gradient_set_pixmap_destination(ScreenPtr screen, + glamor_screen_private *glamor_priv, + PicturePtr dst_picture, + GLfloat *xscale, GLfloat *yscale, + int x_source, int y_source, + float vertices[8], + float tex_vertices[8], + int tex_normalize) +{ + glamor_pixmap_private *pixmap_priv; + PixmapPtr pixmap = NULL; + glamor_gl_dispatch *dispatch = NULL; + float tmp; + + pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ + return 0; + } + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + pixmap_priv_get_dest_scale(pixmap_priv, xscale, yscale); + + DEBUGF("xscale = %f, yscale = %f," + " x_source = %d, y_source = %d, width = %d, height = %d\n", + *xscale, *yscale, x_source, y_source, + dst_picture->pDrawable->width, dst_picture->pDrawable->height); + + glamor_set_normalize_vcoords(*xscale, *yscale, + 0, 0, + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), + glamor_priv->yInverted, vertices); + + if (tex_normalize) { + glamor_set_normalize_tcoords(*xscale, *yscale, + 0, 0, + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), + glamor_priv->yInverted, tex_vertices); + } else { + glamor_set_tcoords(0, 0, + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), + glamor_priv->yInverted, tex_vertices); + } + + DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + vertices[0], vertices[1], vertices[2], vertices[3], + vertices[4], vertices[5], vertices[6], vertices[7]); + DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], + tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); + + /* Swap the vtx for triangle render. */ + tmp = vertices[4]; + vertices[4] = vertices[6]; + vertices[6] = tmp; + tmp = vertices[5]; + vertices[5] = vertices[7]; + vertices[7] = tmp; + + tmp = tex_vertices[4]; + tex_vertices[4] = tex_vertices[6]; + tex_vertices[6] = tmp; + tmp = tex_vertices[5]; + tex_vertices[5] = tex_vertices[7]; + tex_vertices[7] = tmp; + + dispatch = glamor_get_dispatch(glamor_priv); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 0, vertices); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 0, tex_vertices); + + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + glamor_put_dispatch(glamor_priv); + + return 1; +} + +static int +_glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, + GLfloat *stop_colors, GLfloat *n_stops) +{ + int i; + int count = 1; + + for (i = 0; i < pgradient->nstops; i++) { + /* We find some gradient picture set the stops at the same percentage, which + will cause the shader problem because the (stops[i] - stops[i-1]) will + be used as divisor. We just keep the later one if stops[i] == stops[i-1] */ + if (i < pgradient->nstops - 1 + && pgradient->stops[i].x == pgradient->stops[i+1].x) + continue; + + stop_colors[count*4] = pixman_fixed_to_double( + pgradient->stops[i].color.red); + stop_colors[count*4+1] = pixman_fixed_to_double( + pgradient->stops[i].color.green); + stop_colors[count*4+2] = pixman_fixed_to_double( + pgradient->stops[i].color.blue); + stop_colors[count*4+3] = pixman_fixed_to_double( + pgradient->stops[i].color.alpha); + + n_stops[count] = (GLfloat)pixman_fixed_to_double( + pgradient->stops[i].x); + count++; + } + + /* for the end stop. */ + count++; + + switch (src_picture->repeatType) { +#define REPEAT_FILL_STOPS(m, n) \ + stop_colors[(m)*4 + 0] = stop_colors[(n)*4 + 0]; \ + stop_colors[(m)*4 + 1] = stop_colors[(n)*4 + 1]; \ + stop_colors[(m)*4 + 2] = stop_colors[(n)*4 + 2]; \ + stop_colors[(m)*4 + 3] = stop_colors[(n)*4 + 3]; + + default: + case PIXMAN_REPEAT_NONE: + stop_colors[0] = 0.0; //R + stop_colors[1] = 0.0; //G + stop_colors[2] = 0.0; //B + stop_colors[3] = 0.0; //Alpha + n_stops[0] = -(float)INT_MAX; //should be small enough. + + stop_colors[0 + (count-1)*4] = 0.0; //R + stop_colors[1 + (count-1)*4] = 0.0; //G + stop_colors[2 + (count-1)*4] = 0.0; //B + stop_colors[3 + (count-1)*4] = 0.0; //Alpha + n_stops[count-1] = (float)INT_MAX; //should be large enough. + break; + case PIXMAN_REPEAT_NORMAL: + REPEAT_FILL_STOPS(0, count - 2); + n_stops[0] = n_stops[count-2] - 1.0; + + REPEAT_FILL_STOPS(count - 1, 1); + n_stops[count-1] = n_stops[1] + 1.0; + break; + case PIXMAN_REPEAT_REFLECT: + REPEAT_FILL_STOPS(0, 1); + n_stops[0] = -n_stops[1]; + + REPEAT_FILL_STOPS(count - 1, count - 2); + n_stops[count-1] = 1.0 + 1.0 - n_stops[count-2]; + break; + case PIXMAN_REPEAT_PAD: + REPEAT_FILL_STOPS(0, 1); + n_stops[0] = -(float)INT_MAX; + + REPEAT_FILL_STOPS(count - 1, count - 2); + n_stops[count-1] = (float)INT_MAX; + break; +#undef REPEAT_FILL_STOPS + } + + for (i = 0; i < count; i++) { + DEBUGF("n_stops[%d] = %f, color = r:%f g:%f b:%f a:%f\n", + i, n_stops[i], + stop_colors[i*4], stop_colors[i*4+1], + stop_colors[i*4+2], stop_colors[i*4+3]); + } + + return count; +} + +PicturePtr +glamor_generate_radial_gradient_picture(ScreenPtr screen, + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + PicturePtr dst_picture = NULL; + PixmapPtr pixmap = NULL; + GLint gradient_prog = 0; + int error; + float tex_vertices[8]; + int stops_count = 0; + int count = 0; + GLfloat *stop_colors = NULL; + GLfloat *n_stops = NULL; + GLfloat xscale, yscale; + float vertices[8]; + float transform_mat[3][3]; + static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}}; + GLfloat stop_colors_st[RADIAL_SMALL_STOPS*4]; + GLfloat n_stops_st[RADIAL_SMALL_STOPS]; + GLfloat A_value; + GLfloat cxy[4]; + float c1x, c1y, c2x, c2y, r1, r2; + + GLint transform_mat_uniform_location = 0; + GLint repeat_type_uniform_location = 0; + GLint n_stop_uniform_location = 0; + GLint stops_uniform_location = 0; + GLint stop_colors_uniform_location = 0; + GLint stop0_uniform_location = 0; + GLint stop1_uniform_location = 0; + GLint stop2_uniform_location = 0; + GLint stop3_uniform_location = 0; + GLint stop4_uniform_location = 0; + GLint stop5_uniform_location = 0; + GLint stop6_uniform_location = 0; + GLint stop7_uniform_location = 0; + GLint stop_color0_uniform_location = 0; + GLint stop_color1_uniform_location = 0; + GLint stop_color2_uniform_location = 0; + GLint stop_color3_uniform_location = 0; + GLint stop_color4_uniform_location = 0; + GLint stop_color5_uniform_location = 0; + GLint stop_color6_uniform_location = 0; + GLint stop_color7_uniform_location = 0; + GLint A_value_uniform_location = 0; + GLint c1_uniform_location = 0; + GLint r1_uniform_location = 0; + GLint c2_uniform_location = 0; + GLint r2_uniform_location = 0; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + /* Create a pixmap with VBO. */ + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), + 0); + if (!pixmap) + goto GRADIENT_FAIL; + + dst_picture = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), format), + 0, 0, serverClient, &error); + + /* Release the reference, picture will hold the last one. */ + glamor_destroy_pixmap(pixmap); + + if (!dst_picture) + goto GRADIENT_FAIL; + + ValidatePicture(dst_picture); + + stops_count = src_picture->pSourcePict->radial.nstops + 2; + + /* Because the max value of nstops is unkown, so create a program + when nstops > LINEAR_LARGE_STOPS.*/ + if (stops_count <= RADIAL_SMALL_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][0]; + } else if (stops_count <= RADIAL_LARGE_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][1]; + } else { + _glamor_create_radial_gradient_program(screen, + src_picture->pSourcePict->linear.nstops + 2, + 1); + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]; + } + + /* Bind all the uniform vars .*/ + transform_mat_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + n_stop_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "n_stop"); + A_value_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "A_value"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + c1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "c1"); + r1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "r1"); + c2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "c2"); + r2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "r2"); + + if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) { + stop0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop0"); + stop1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop1"); + stop2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop2"); + stop3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop3"); + stop4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop4"); + stop5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop5"); + stop6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop6"); + stop7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop7"); + + stop_color0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); + stop_color1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); + stop_color2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); + stop_color3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); + stop_color4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); + stop_color5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); + stop_color6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); + stop_color7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); + } else { + stops_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stops"); + stop_colors_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); + } + + dispatch->glUseProgram(gradient_prog); + + dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); + + + if (src_picture->transform) { + _glamor_gradient_convert_trans_matrix(src_picture->transform, + transform_mat, + width, height, 0); + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &transform_mat[0][0]); + } else { + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &identity_mat[0][0]); + } + + if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, + &xscale, &yscale, x_source, y_source, + vertices, tex_vertices, 0)) + goto GRADIENT_FAIL; + + /* Set all the stops and colors to shader. */ + if (stops_count > RADIAL_SMALL_STOPS) { + stop_colors = malloc(4 * stops_count * sizeof(float)); + if (stop_colors == NULL) { + ErrorF("Failed to allocate stop_colors memory.\n"); + goto GRADIENT_FAIL; + } + + n_stops = malloc(stops_count * sizeof(float)); + if (n_stops == NULL) { + ErrorF("Failed to allocate n_stops memory.\n"); + goto GRADIENT_FAIL; + } + } else { + stop_colors = stop_colors_st; + n_stops = n_stops_st; + } + + count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, + stop_colors, n_stops); + + if (src_picture->pSourcePict->linear.nstops + 2 <= RADIAL_SMALL_STOPS) { + int j = 0; + dispatch->glUniform4f(stop_color0_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color1_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color2_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color3_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color4_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color5_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color6_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color7_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + + j = 0; + dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); + dispatch->glUniform1i(n_stop_uniform_location, count); + } else { + dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); + dispatch->glUniform1fv(stops_uniform_location, count, n_stops); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + + c1x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.x); + c1y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.y); + c2x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.x); + c2y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.y); + + r1 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.radius); + r2 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.radius); + + + cxy[0] = c1x; + cxy[1] = c1y; + dispatch->glUniform2fv(c1_uniform_location, 1, cxy); + dispatch->glUniform1f(r1_uniform_location, r1); + + cxy[0] = c2x; + cxy[1] = c2y; + dispatch->glUniform2fv(c2_uniform_location, 1, cxy); + dispatch->glUniform1f(r2_uniform_location, r2); + + A_value = (c2x - c1x) * (c2x - c1x) + (c2y - c1y) * (c2y - c1y) - (r2 - r1) * (r2 - r1); + dispatch->glUniform1f(A_value_uniform_location, A_value); + + DEBUGF("C1:(%f, %f) R1:%f\nC2:(%f, %f) R2:%f\nA = %f\n", + c1x, c1y, r1, c2x, c2y, r2, A_value); + + /* Now rendering. */ + dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* Do the clear logic.*/ + if (stops_count > RADIAL_SMALL_STOPS) { + free(n_stops); + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); + return dst_picture; + +GRADIENT_FAIL: + if (dst_picture) { + FreePicture(dst_picture, 0); + } + + if (stops_count > RADIAL_SMALL_STOPS) { + if (n_stops) + free(n_stops); + if (stop_colors) + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); + return NULL; +} + +PicturePtr +glamor_generate_linear_gradient_picture(ScreenPtr screen, + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + PicturePtr dst_picture = NULL; + PixmapPtr pixmap = NULL; + GLint gradient_prog = 0; + int error; + float pt_distance; + float p1_distance; + GLfloat cos_val; + float tex_vertices[8]; + int stops_count = 0; + GLfloat *stop_colors = NULL; + GLfloat *n_stops = NULL; + int count = 0; + float slope; + GLfloat xscale, yscale; + GLfloat pt1[4], pt2[4]; + float vertices[8]; + float transform_mat[3][3]; + static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}}; + GLfloat stop_colors_st[LINEAR_SMALL_STOPS*4]; + GLfloat n_stops_st[LINEAR_SMALL_STOPS]; + + GLint transform_mat_uniform_location = 0; + GLint pt1_uniform_location = 0; + GLint pt2_uniform_location = 0; + GLint n_stop_uniform_location = 0; + GLint stops_uniform_location = 0; + GLint stop0_uniform_location = 0; + GLint stop1_uniform_location = 0; + GLint stop2_uniform_location = 0; + GLint stop3_uniform_location = 0; + GLint stop4_uniform_location = 0; + GLint stop5_uniform_location = 0; + GLint stop6_uniform_location = 0; + GLint stop7_uniform_location = 0; + GLint stop_colors_uniform_location = 0; + GLint stop_color0_uniform_location = 0; + GLint stop_color1_uniform_location = 0; + GLint stop_color2_uniform_location = 0; + GLint stop_color3_uniform_location = 0; + GLint stop_color4_uniform_location = 0; + GLint stop_color5_uniform_location = 0; + GLint stop_color6_uniform_location = 0; + GLint stop_color7_uniform_location = 0; + GLint pt_slope_uniform_location = 0; + GLint repeat_type_uniform_location = 0; + GLint hor_ver_uniform_location = 0; + GLint cos_val_uniform_location = 0; + GLint p1_distance_uniform_location = 0; + GLint pt_distance_uniform_location = 0; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + /* Create a pixmap with VBO. */ + pixmap = glamor_create_pixmap(screen, + width, height, + PIXMAN_FORMAT_DEPTH(format), + 0); + + if (!pixmap) + goto GRADIENT_FAIL; + + dst_picture = CreatePicture(0, &pixmap->drawable, + PictureMatchFormat(screen, + PIXMAN_FORMAT_DEPTH(format), format), + 0, 0, serverClient, &error); + + /* Release the reference, picture will hold the last one. */ + glamor_destroy_pixmap(pixmap); + + if (!dst_picture) + goto GRADIENT_FAIL; + + ValidatePicture(dst_picture); + + stops_count = src_picture->pSourcePict->linear.nstops + 2; + + /* Because the max value of nstops is unkown, so create a program + when nstops > LINEAR_LARGE_STOPS.*/ + if (stops_count <= LINEAR_SMALL_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][0]; + } else if (stops_count <= LINEAR_LARGE_STOPS) { + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][1]; + } else { + _glamor_create_linear_gradient_program(screen, + src_picture->pSourcePict->linear.nstops + 2, 1); + gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]; + } + + /* Bind all the uniform vars .*/ + pt1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt1"); + pt2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt2"); + n_stop_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "n_stop"); + pt_slope_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt_slope"); + repeat_type_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); + hor_ver_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "hor_ver"); + transform_mat_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); + cos_val_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "cos_val"); + p1_distance_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "p1_distance"); + pt_distance_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "pt_distance"); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { + stop0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop0"); + stop1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop1"); + stop2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop2"); + stop3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop3"); + stop4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop4"); + stop5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop5"); + stop6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop6"); + stop7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop7"); + + stop_color0_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); + stop_color1_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); + stop_color2_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); + stop_color3_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); + stop_color4_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); + stop_color5_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); + stop_color6_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); + stop_color7_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); + } else { + stops_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stops"); + stop_colors_uniform_location = + dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); + } + + dispatch->glUseProgram(gradient_prog); + + dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); + + /* set the transform matrix. */ + if (src_picture->transform) { + _glamor_gradient_convert_trans_matrix(src_picture->transform, + transform_mat, + width, height, 1); + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &transform_mat[0][0]); + } else { + dispatch->glUniformMatrix3fv(transform_mat_uniform_location, + 1, 1, &identity_mat[0][0]); + } + + if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, + &xscale, &yscale, x_source, y_source, + vertices, tex_vertices, 1)) + goto GRADIENT_FAIL; + + /* Normalize the PTs. */ + glamor_set_normalize_pt(xscale, yscale, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.x), + x_source, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.y), + y_source, + glamor_priv->yInverted, + pt1); + dispatch->glUniform4fv(pt1_uniform_location, 1, pt1); + DEBUGF("pt1:(%f %f)\n", pt1[0], pt1[1]); + + glamor_set_normalize_pt(xscale, yscale, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.x), + x_source, + pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.y), + y_source, + glamor_priv->yInverted, + pt2); + dispatch->glUniform4fv(pt2_uniform_location, 1, pt2); + DEBUGF("pt2:(%f %f)\n", pt2[0], pt2[1]); + + /* Set all the stops and colors to shader. */ + if (stops_count > LINEAR_SMALL_STOPS) { + stop_colors = malloc(4 * stops_count * sizeof(float)); + if (stop_colors == NULL) { + ErrorF("Failed to allocate stop_colors memory.\n"); + goto GRADIENT_FAIL; + } + + n_stops = malloc(stops_count * sizeof(float)); + if (n_stops == NULL) { + ErrorF("Failed to allocate n_stops memory.\n"); + goto GRADIENT_FAIL; + } + } else { + stop_colors = stop_colors_st; + n_stops = n_stops_st; + } + + count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, + stop_colors, n_stops); + + if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { + int j = 0; + dispatch->glUniform4f(stop_color0_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color1_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color2_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color3_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color4_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color5_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color6_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + j++; + dispatch->glUniform4f(stop_color7_uniform_location, + stop_colors[4*j+0], stop_colors[4*j+1], + stop_colors[4*j+2], stop_colors[4*j+3]); + + j = 0; + dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); + dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); + + dispatch->glUniform1i(n_stop_uniform_location, count); + } else { + dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); + dispatch->glUniform1fv(stops_uniform_location, count, n_stops); + dispatch->glUniform1i(n_stop_uniform_location, count); + } + + if (abs((pt2[1] - pt1[1]) / yscale) < 1.0) { // The horizontal case. + dispatch->glUniform1i(hor_ver_uniform_location, 1); + DEBUGF("p1.x: %f, p2.x: %f, enter the horizontal case\n", pt1[1], pt2[1]); + + p1_distance = pt1[0]; + pt_distance = (pt2[0] - p1_distance); + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } else if (abs((pt2[0] - pt1[0]) / xscale) < 1.0) { //The vertical case. + dispatch->glUniform1i(hor_ver_uniform_location, 2); + DEBUGF("p1.y: %f, p2.y: %f, enter the vertical case\n", pt1[0], pt2[0]); + + p1_distance = pt1[1]; + pt_distance = (pt2[1] - p1_distance); + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } else { + /* The slope need to compute here. In shader, the viewport set will change + the orginal slope and the slope which is vertical to it will not be correct.*/ + slope = - (float)(src_picture->pSourcePict->linear.p2.x + - src_picture->pSourcePict->linear.p1.x) / + (float)(src_picture->pSourcePict->linear.p2.y + - src_picture->pSourcePict->linear.p1.y); + slope = slope * yscale / xscale; + dispatch->glUniform1f(pt_slope_uniform_location, slope); + dispatch->glUniform1i(hor_ver_uniform_location, 0); + + cos_val = sqrt(1.0 / (slope * slope + 1.0)); + dispatch->glUniform1f(cos_val_uniform_location, cos_val); + + p1_distance = (pt1[1] - pt1[0] * slope) * cos_val; + pt_distance = (pt2[1] - pt2[0] * slope) * cos_val - p1_distance; + dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); + dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); + } + + /* Now rendering. */ + dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* Do the clear logic.*/ + if (stops_count > LINEAR_SMALL_STOPS) { + free(n_stops); + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); + return dst_picture; + +GRADIENT_FAIL: + if (dst_picture) { + FreePicture(dst_picture, 0); + } + + if (stops_count > LINEAR_SMALL_STOPS) { + if (n_stops) + free(n_stops); + if (stop_colors) + free(stop_colors); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); + return NULL; +} + +#endif /* End of GLAMOR_GRADIENT_SHADER */ + +#endif /* End of RENDER */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 8f1d42876..a817f78a5 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -577,8 +577,19 @@ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, void glamor_init_tile_shader(ScreenPtr screen); void glamor_fini_tile_shader(ScreenPtr screen); +/* glamor_gradient.c */ void glamor_init_gradient_shader(ScreenPtr screen); void glamor_fini_gradient_shader(ScreenPtr screen); +PicturePtr glamor_generate_linear_gradient_picture(ScreenPtr screen, + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format); +PicturePtr glamor_generate_radial_gradient_picture(ScreenPtr screen, + PicturePtr src_picture, + int x_source, int y_source, + int width, int height, + PictFormatShort format); /* glamor_triangles.c */ void @@ -744,7 +755,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #ifndef GLAMOR_GLES2 -//#define GLAMOR_GRADIENT_SHADER +#define GLAMOR_GRADIENT_SHADER #endif #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 94f7dc5a5..907d65b8e 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -744,7 +744,6 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; - glamor_priv->vbo_offset = 0; glamor_priv->vbo_offset = 0; glamor_priv->render_nr_verts = 0; glamor_priv->vbo_size = n_verts * sizeof(float) * 2; @@ -1339,1583 +1338,6 @@ done: return ret; } -#ifdef GLAMOR_GRADIENT_SHADER -static GLint -_glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_array) -{ - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - - char *gradient_fs = NULL; - GLint fs_getcolor_prog; - - const char *gradient_fs_getcolor = - GLAMOR_DEFAULT_PRECISION - "uniform int n_stop;\n" - "uniform float stops[%d];\n" - "uniform vec4 stop_colors[%d];\n" - "vec4 get_color(float stop_len)\n" - "{\n" - " int i = 0;\n" - " float new_alpha; \n" - " vec4 gradient_color;\n" - " float percentage; \n" - " for(i = 0; i < n_stop - 1; i++) {\n" - " if(stop_len < stops[i])\n" - " break; \n" - " }\n" - " \n" - " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n" - " if(stops[i] - stops[i-1] > 2.0)\n" - " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. - " new_alpha = percentage * stop_colors[i].a + \n" - " (1.0-percentage) * stop_colors[i-1].a; \n" - " gradient_color = vec4((percentage * stop_colors[i].rgb \n" - " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n" - " new_alpha);\n" - " \n" - " return gradient_color;\n" - "}\n"; - - /* Because the array access for shader is very slow, the performance is very low - if use array. So use global uniform to replace for it if the number of n_stops is small.*/ - const char *gradient_fs_getcolor_no_array = - GLAMOR_DEFAULT_PRECISION - "uniform int n_stop;\n" - "uniform float stop0;\n" - "uniform float stop1;\n" - "uniform float stop2;\n" - "uniform float stop3;\n" - "uniform float stop4;\n" - "uniform float stop5;\n" - "uniform float stop6;\n" - "uniform float stop7;\n" - "uniform vec4 stop_color0;\n" - "uniform vec4 stop_color1;\n" - "uniform vec4 stop_color2;\n" - "uniform vec4 stop_color3;\n" - "uniform vec4 stop_color4;\n" - "uniform vec4 stop_color5;\n" - "uniform vec4 stop_color6;\n" - "uniform vec4 stop_color7;\n" - "\n" - "vec4 get_color(float stop_len)\n" - "{\n" - " float stop_after;\n" - " float stop_before;\n" - " vec4 stop_color_before;\n" - " vec4 stop_color_after;\n" - " float new_alpha; \n" - " vec4 gradient_color;\n" - " float percentage; \n" - " \n" - " if((stop_len < stop0) && (n_stop >= 1)) {\n" - " stop_color_before = stop_color0;\n" - " stop_color_after = stop_color0;\n" - " stop_after = stop0;\n" - " stop_before = stop0;\n" - " percentage = 0.0;\n" - " } else if((stop_len < stop1) && (n_stop >= 2)) {\n" - " stop_color_before = stop_color0;\n" - " stop_color_after = stop_color1;\n" - " stop_after = stop1;\n" - " stop_before = stop0;\n" - " percentage = (stop_len - stop0)/(stop1 - stop0);\n" - " } else if((stop_len < stop2) && (n_stop >= 3)) {\n" - " stop_color_before = stop_color1;\n" - " stop_color_after = stop_color2;\n" - " stop_after = stop2;\n" - " stop_before = stop1;\n" - " percentage = (stop_len - stop1)/(stop2 - stop1);\n" - " } else if((stop_len < stop3) && (n_stop >= 4)){\n" - " stop_color_before = stop_color2;\n" - " stop_color_after = stop_color3;\n" - " stop_after = stop3;\n" - " stop_before = stop2;\n" - " percentage = (stop_len - stop2)/(stop3 - stop2);\n" - " } else if((stop_len < stop4) && (n_stop >= 5)){\n" - " stop_color_before = stop_color3;\n" - " stop_color_after = stop_color4;\n" - " stop_after = stop4;\n" - " stop_before = stop3;\n" - " percentage = (stop_len - stop3)/(stop4 - stop3);\n" - " } else if((stop_len < stop5) && (n_stop >= 6)){\n" - " stop_color_before = stop_color4;\n" - " stop_color_after = stop_color5;\n" - " stop_after = stop5;\n" - " stop_before = stop4;\n" - " percentage = (stop_len - stop4)/(stop5 - stop4);\n" - " } else if((stop_len < stop6) && (n_stop >= 7)){\n" - " stop_color_before = stop_color5;\n" - " stop_color_after = stop_color6;\n" - " stop_after = stop6;\n" - " stop_before = stop5;\n" - " percentage = (stop_len - stop5)/(stop6 - stop5);\n" - " } else if((stop_len < stop7) && (n_stop >= 8)){\n" - " stop_color_before = stop_color6;\n" - " stop_color_after = stop_color7;\n" - " stop_after = stop7;\n" - " stop_before = stop6;\n" - " percentage = (stop_len - stop6)/(stop7 - stop6);\n" - " } else {\n" - " stop_color_before = stop_color7;\n" - " stop_color_after = stop_color7;\n" - " stop_after = stop7;\n" - " stop_before = stop7;\n" - " percentage = 0.0;\n" - " }\n" - " if(stop_after - stop_before > 2.0)\n" - " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. - " new_alpha = percentage * stop_color_after.a + \n" - " (1.0-percentage) * stop_color_before.a; \n" - " gradient_color = vec4((percentage * stop_color_after.rgb \n" - " + (1.0-percentage) * stop_color_before.rgb)*new_alpha, \n" - " new_alpha);\n" - " \n" - " return gradient_color;\n" - "}\n"; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - if(use_array) { - XNFasprintf(&gradient_fs, - gradient_fs_getcolor, stops_count, stops_count); - fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - gradient_fs); - free(gradient_fs); - } else { - fs_getcolor_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, - gradient_fs_getcolor_no_array); - } - - return fs_getcolor_prog; -} - -static void -_glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) -{ - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - int index; - - GLint gradient_prog = 0; - char *gradient_fs = NULL; - GLint fs_main_prog, fs_getcolor_prog, vs_prog; - - const char *gradient_vs = - GLAMOR_DEFAULT_PRECISION - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord;\n" - "varying vec2 source_texture;\n" - "\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - " source_texture = v_texcoord.xy;\n" - "}\n"; - - /* - * Refer to pixman radial gradient. - * - * The problem is given the two circles of c1 and c2 with the radius of r1 and - * r1, we need to caculate the t, which is used to do interpolate with stops, - * using the fomula: - * length((1-t)*c1 + t*c2 - p) = (1-t)*r1 + t*r2 - * expand the fomula with xy coond, get the following: - * sqrt(sqr((1-t)*c1.x + t*c2.x - p.x) + sqr((1-t)*c1.y + t*c2.y - p.y)) - * = (1-t)r1 + t*r2 - * <====> At*t- 2Bt + C = 0 - * where A = sqr(c2.x - c1.x) + sqr(c2.y - c1.y) - sqr(r2 -r1) - * B = (p.x - c1.x)*(c2.x - c1.x) + (p.y - c1.y)*(c2.y - c1.y) + r1*(r2 -r1) - * C = sqr(p.x - c1.x) + sqr(p.y - c1.y) - r1*r1 - * - * solve the fomula and we get the result of - * t = (B + sqrt(B*B - A*C)) / A or - * t = (B - sqrt(B*B - A*C)) / A (quadratic equation have two solutions) - * - * The solution we are going to prefer is the bigger one, unless the - * radius associated to it is negative (or it falls outside the valid t range) - */ - - const char *gradient_fs_template = - GLAMOR_DEFAULT_PRECISION - "uniform mat3 transform_mat;\n" - "uniform int repeat_type;\n" - "uniform float A_value;\n" - "uniform vec2 c1;\n" - "uniform float r1;\n" - "uniform vec2 c2;\n" - "uniform float r2;\n" - "varying vec2 source_texture;\n" - "\n" - "vec4 get_color(float stop_len);\n" - "\n" - "int t_invalid;\n" - "\n" - "float get_stop_len()\n" - "{\n" - " float t = 0.0;\n" - " float sqrt_value;\n" - " int revserse = 0;\n" - " t_invalid = 0;\n" - " \n" - " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" - " vec3 source_texture_trans = transform_mat * tmp;\n" - " source_texture_trans.xy = source_texture_trans.xy/source_texture_trans.z;\n" - " float B_value = (source_texture_trans.x - c1.x) * (c2.x - c1.x)\n" - " + (source_texture_trans.y - c1.y) * (c2.y - c1.y)\n" - " + r1 * (r2 - r1);\n" - " float C_value = (source_texture_trans.x - c1.x) * (source_texture_trans.x - c1.x)\n" - " + (source_texture_trans.y - c1.y) * (source_texture_trans.y - c1.y)\n" - " - r1*r1;\n" - " if(abs(A_value) < 0.00001) {\n" - " if(B_value == 0.0) {\n" - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " t = 0.5 * C_value / B_value;" - " } else {\n" - " sqrt_value = B_value * B_value - A_value * C_value;\n" - " if(sqrt_value < 0.0) {\n" - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " sqrt_value = sqrt(sqrt_value);\n" - " t = (B_value + sqrt_value) / A_value;\n" - " }\n" - " if(repeat_type == %d) {\n" // RepeatNone case. - " if((t <= 0.0) || (t > 1.0))\n" - // try another if first one invalid - " t = (B_value - sqrt_value) / A_value;\n" - " \n" - " if((t <= 0.0) || (t > 1.0)) {\n" //still invalid, return. - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " } else {\n" - " if(t * (r2 - r1) <= -1.0 * r1)\n" - // try another if first one invalid - " t = (B_value - sqrt_value) / A_value;\n" - " \n" - " if(t * (r2 -r1) <= -1.0 * r1) {\n" //still invalid, return. - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " }\n" - " \n" - " if(repeat_type == %d){\n" // repeat normal - " while(t > 1.0) \n" - " t = t - 1.0; \n" - " while(t < 0.0) \n" - " t = t + 1.0; \n" - " }\n" - " \n" - " if(repeat_type == %d) {\n" // repeat reflect - " while(t > 1.0) {\n" - " t = t - 1.0; \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " while(t < 0.0) {\n" - " t = t + 1.0; \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " if(revserse == 1) {\n" - " t = 1.0 - t; \n" - " }\n" - " }\n" - " \n" - " return t;\n" - "}\n" - "\n" - "void main()\n" - "{\n" - " float stop_len = get_stop_len();\n" - " if(t_invalid == 1) {\n" - " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" - " } else {\n" - " gl_FragColor = get_color(stop_len);\n" - " }\n" - "}\n"; - - glamor_priv = glamor_get_screen_private(screen); - - if ((glamor_priv->radial_max_nstops >= stops_count) && (dyn_gen)) { - /* Very Good, not to generate again. */ - return; - } - - dispatch = glamor_get_dispatch(glamor_priv); - - if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) { - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; - - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]); - glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0; - } - - gradient_prog = dispatch->glCreateProgram(); - - vs_prog = glamor_compile_glsl_prog(dispatch, - GL_VERTEX_SHADER, gradient_vs); - - XNFasprintf(&gradient_fs, - gradient_fs_template, - PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); - - fs_main_prog = glamor_compile_glsl_prog(dispatch, - GL_FRAGMENT_SHADER, gradient_fs); - - free(gradient_fs); - - fs_getcolor_prog = - _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); - - dispatch->glAttachShader(gradient_prog, vs_prog); - dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); - dispatch->glAttachShader(gradient_prog, fs_main_prog); - - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_positionsition"); - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); - - glamor_link_glsl_prog(dispatch, gradient_prog); - - dispatch->glUseProgram(0); - - if (dyn_gen) { - index = 2; - glamor_priv->radial_max_nstops = stops_count; - } else if (stops_count) { - index = 1; - } else { - index = 0; - } - - glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; - - glamor_put_dispatch(glamor_priv); -} - -static void -_glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dyn_gen) -{ - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - - int index = 0; - GLint gradient_prog = 0; - char *gradient_fs = NULL; - GLint fs_main_prog, fs_getcolor_prog, vs_prog; - - const char *gradient_vs = - GLAMOR_DEFAULT_PRECISION - "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord;\n" - "varying vec2 source_texture;\n" - "\n" - "void main()\n" - "{\n" - " gl_Position = v_position;\n" - " source_texture = v_texcoord.xy;\n" - "}\n"; - - /* - * | - * |\ - * | \ - * | \ - * | \ - * |\ \ - * | \ \ - * cos_val = |\ p1d \ / - * sqrt(1/(slope*slope+1.0)) ------>\ \ \ / - * | \ \ \ - * | \ \ / \ - * | \ *Pt1\ - * *p1 | \ \ *P - * \ | / \ \ / - * \ | / \ \ / - * \ | pd \ - * \ | \ / \ - * p2* | \ / \ / - * slope = (p2.y - p1.y) / | / p2d / - * (p2.x - p1.x) | / \ / - * | / \ / - * | / / - * | / / - * | / *Pt2 - * | / - * | / - * | / - * | / - * | / - * -------+--------------------------------- - * O| - * | - * | - * - * step 1: compute the distance of p, pt1 and pt2 in the slope direction. - * Caculate the distance on Y axis first and multiply cos_val to - * get the value on slope direction(pd, p1d and p2d represent the - * distance of p, pt1, and pt2 respectively). - * - * step 2: caculate the percentage of (pd - p1d)/(p2d - p1d). - * If (pd - p1d) > (p2d - p1d) or < 0, then sub or add (p2d - p1d) - * to make it in the range of [0, (p2d - p1d)]. - * - * step 3: compare the percentage to every stop and find the stpos just - * before and after it. Use the interpolation fomula to compute RGBA. - */ - - const char *gradient_fs_template = - GLAMOR_DEFAULT_PRECISION - "uniform mat3 transform_mat;\n" - "uniform int repeat_type;\n" - "uniform int hor_ver;\n" - "uniform vec4 pt1;\n" - "uniform vec4 pt2;\n" - "uniform float pt_slope;\n" - "uniform float cos_val;\n" - "uniform float p1_distance;\n" - "uniform float pt_distance;\n" - "varying vec2 source_texture;\n" - "\n" - "vec4 get_color(float stop_len);\n" - "\n" - "float get_stop_len()\n" - "{\n" - " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" - " float len_percentage;\n" - " float distance;\n" - " float _p1_distance;\n" - " float _pt_distance;\n" - " float y_dist;\n" - " float stop_after;\n" - " float stop_before;\n" - " vec4 stop_color_before;\n" - " vec4 stop_color_after;\n" - " float new_alpha; \n" - " int revserse = 0;\n" - " vec4 gradient_color;\n" - " float percentage; \n" - " vec3 source_texture_trans = transform_mat * tmp;\n" - " \n" - " if(hor_ver == 0) { \n" //Normal case. - " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n" - " distance = y_dist * cos_val;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " \n" - " } else if (hor_ver == 1) {\n"//horizontal case. - " distance = source_texture_trans.x;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " } else if (hor_ver == 2) {\n"//vertical case. - " distance = source_texture_trans.y;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " } \n" - " \n" - " distance = distance - _p1_distance; \n" - " \n" - " if(repeat_type == %d){\n" // repeat normal - " while(distance > _pt_distance) \n" - " distance = distance - (_pt_distance); \n" - " while(distance < 0.0) \n" - " distance = distance + (_pt_distance); \n" - " }\n" - " \n" - " if(repeat_type == %d) {\n" // repeat reflect - " while(distance > _pt_distance) {\n" - " distance = distance - (_pt_distance); \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " while(distance < 0.0) {\n" - " distance = distance + (_pt_distance); \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " if(revserse == 1) {\n" - " distance = (_pt_distance) - distance; \n" - " }\n" - " }\n" - " \n" - " len_percentage = distance/(_pt_distance);\n" - " \n" - " return len_percentage;\n" - "}\n" - "\n" - "void main()\n" - "{\n" - " float stop_len = get_stop_len();\n" - " gl_FragColor = get_color(stop_len);\n" - "}\n"; - - - glamor_priv = glamor_get_screen_private(screen); - - if ((glamor_priv->linear_max_nstops >= stops_count) && (dyn_gen)) { - /* Very Good, not to generate again. */ - return; - } - - dispatch = glamor_get_dispatch(glamor_priv); - if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) { - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2]); - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2]); - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] = 0; - - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2]); - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0; - - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]); - glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0; - } - - gradient_prog = dispatch->glCreateProgram(); - - vs_prog = glamor_compile_glsl_prog(dispatch, - GL_VERTEX_SHADER, gradient_vs); - - XNFasprintf(&gradient_fs, - gradient_fs_template, - PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); - - fs_main_prog = glamor_compile_glsl_prog(dispatch, - GL_FRAGMENT_SHADER, gradient_fs); - free(gradient_fs); - - fs_getcolor_prog = - _glamor_create_getcolor_fs_program(screen, stops_count, (stops_count > 0)); - - dispatch->glAttachShader(gradient_prog, vs_prog); - dispatch->glAttachShader(gradient_prog, fs_getcolor_prog); - dispatch->glAttachShader(gradient_prog, fs_main_prog); - - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position"); - dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord"); - - glamor_link_glsl_prog(dispatch, gradient_prog); - - dispatch->glUseProgram(0); - - if (dyn_gen) { - index = 2; - glamor_priv->linear_max_nstops = stops_count; - } else if (stops_count) { - index = 1; - } else { - index = 0; - } - - glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] = vs_prog; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] = fs_main_prog; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] = fs_getcolor_prog; - - glamor_put_dispatch(glamor_priv); -} - -#define LINEAR_SMALL_STOPS 6 + 2 -#define LINEAR_LARGE_STOPS 16 + 2 - -#define RADIAL_SMALL_STOPS 6 + 2 -#define RADIAL_LARGE_STOPS 16 + 2 - -void -glamor_init_gradient_shader(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - int i; - - glamor_priv = glamor_get_screen_private(screen); - - for (i = 0; i < 3; i++) { - glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i] = 0; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; - - glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i] = 0; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] = 0; - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0; - } - glamor_priv->linear_max_nstops = 0; - glamor_priv->radial_max_nstops = 0; - - _glamor_create_linear_gradient_program(screen, 0, 0); - _glamor_create_linear_gradient_program(screen, LINEAR_LARGE_STOPS, 0); - - _glamor_create_radial_gradient_program(screen, 0, 0); - _glamor_create_radial_gradient_program(screen, RADIAL_LARGE_STOPS, 0); -} - -void -glamor_fini_gradient_shader(ScreenPtr screen) -{ - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - int i = 0; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - for (i = 0; i < 3; i++) { - /* Linear Gradient */ - if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); - - if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); - - if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); - - if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]) - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i]); - - /* Radial Gradient */ - if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i]); - - if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i]); - - if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]) - dispatch->glDeleteShader( - glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i]); - - if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]) - dispatch->glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i]); - } - - glamor_put_dispatch(glamor_priv); -} - -static void -_glamor_gradient_convert_trans_matrix(PictTransform *from, float to[3][3], - int width, int height, int normalize) -{ - /* - * Because in the shader program, we normalize all the pixel cood to [0, 1], - * so with the transform matrix, the correct logic should be: - * v_s = A*T*v - * v_s: point vector in shader after normalized. - * A: The transition matrix from width X height --> 1.0 X 1.0 - * T: The transform matrix. - * v: point vector in width X height space. - * - * result is OK if we use this fomula. But for every point in width X height space, - * we can just use their normalized point vector in shader, namely we can just - * use the result of A*v in shader. So we have no chance to insert T in A*v. - * We can just convert v_s = A*T*v to v_s = A*T*inv(A)*A*v, where inv(A) is the - * inverse matrix of A. Now, v_s = (A*T*inv(A)) * (A*v) - * So, to get the correct v_s, we need to cacula1 the matrix: (A*T*inv(A)), and - * we name this matrix T_s. - * - * Firstly, because A is for the scale convertion, we find - * -- -- - * |1/w 0 0 | - * A = | 0 1/h 0 | - * | 0 0 1.0| - * -- -- - * so T_s = A*T*inv(a) and result - * - * -- -- - * | t11 h*t12/w t13/w| - * T_s = | w*t21/h t22 t23/h| - * | w*t31 h*t32 t33 | - * -- -- - */ - - to[0][0] = (float)pixman_fixed_to_double(from->matrix[0][0]); - to[0][1] = (float)pixman_fixed_to_double(from->matrix[0][1]) - * (normalize ? (((float)height) / ((float)width)) : 1.0); - to[0][2] = (float)pixman_fixed_to_double(from->matrix[0][2]) - / (normalize ? ((float)width) : 1.0); - - to[1][0] = (float)pixman_fixed_to_double(from->matrix[1][0]) - * (normalize ? (((float)width) / ((float)height)) : 1.0); - to[1][1] = (float)pixman_fixed_to_double(from->matrix[1][1]); - to[1][2] = (float)pixman_fixed_to_double(from->matrix[1][2]) - / (normalize ? ((float)height) : 1.0); - - to[2][0] = (float)pixman_fixed_to_double(from->matrix[2][0]) - * (normalize ? ((float)width) : 1.0); - to[2][1] = (float)pixman_fixed_to_double(from->matrix[2][1]) - * (normalize ? ((float)height) : 1.0); - to[2][2] = (float)pixman_fixed_to_double(from->matrix[2][2]); - - DEBUGF("the transform matrix is:\n%f\t%f\t%f\n%f\t%f\t%f\n%f\t%f\t%f\n", - to[0][0], to[0][1], to[0][2], - to[1][0], to[1][1], to[1][2], - to[2][0], to[2][1], to[2][2]); -} - -static int -_glamor_gradient_set_pixmap_destination(ScreenPtr screen, - glamor_screen_private *glamor_priv, - PicturePtr dst_picture, - GLfloat *xscale, GLfloat *yscale, - int x_source, int y_source, - float vertices[8], - float tex_vertices[8], - int tex_normalize) -{ - glamor_pixmap_private *pixmap_priv; - PixmapPtr pixmap = NULL; - - pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); - pixmap_priv = glamor_get_pixmap_private(pixmap); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ - return 0; - } - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - - pixmap_priv_get_dest_scale(pixmap_priv, xscale, yscale); - - glamor_priv->has_source_coords = 1; - glamor_priv->has_mask_coords = 0; - glamor_setup_composite_vbo(screen, 4*2); - - DEBUGF("xscale = %f, yscale = %f," - " x_source = %d, y_source = %d, width = %d, height = %d\n", - *xscale, *yscale, x_source, y_source, - dst_picture->pDrawable->width, dst_picture->pDrawable->height); - - glamor_set_normalize_vcoords(*xscale, *yscale, - 0, 0, - (INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - glamor_priv->yInverted, vertices); - - if (tex_normalize) { - glamor_set_normalize_tcoords(*xscale, *yscale, - 0, 0, - (INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - glamor_priv->yInverted, tex_vertices); - } else { - glamor_set_tcoords(0, 0, - (INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - glamor_priv->yInverted, tex_vertices); - } - - DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," - "rightbottom: %f X %f, leftbottom : %f X %f\n", - vertices[0], vertices[1], vertices[2], vertices[3], - vertices[4], vertices[5], vertices[6], vertices[7]); - DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," - "rightbottom: %f X %f, leftbottom : %f X %f\n", - tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], - tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); - - return 1; -} - -static int -_glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, - GLfloat *stop_colors, GLfloat *n_stops) -{ - int i; - int count = 1; - - for (i = 0; i < pgradient->nstops; i++) { - /* We find some gradient picture set the stops at the same percentage, which - will cause the shader problem because the (stops[i] - stops[i-1]) will - be used as divisor. We just keep the later one if stops[i] == stops[i-1] */ - if (i < pgradient->nstops - 1 - && pgradient->stops[i].x == pgradient->stops[i+1].x) - continue; - - stop_colors[count*4] = pixman_fixed_to_double( - pgradient->stops[i].color.red); - stop_colors[count*4+1] = pixman_fixed_to_double( - pgradient->stops[i].color.green); - stop_colors[count*4+2] = pixman_fixed_to_double( - pgradient->stops[i].color.blue); - stop_colors[count*4+3] = pixman_fixed_to_double( - pgradient->stops[i].color.alpha); - - n_stops[count] = (GLfloat)pixman_fixed_to_double( - pgradient->stops[i].x); - count++; - } - - /* for the end stop. */ - count++; - - switch (src_picture->repeatType) { -#define REPEAT_FILL_STOPS(m, n) \ - stop_colors[(m)*4 + 0] = stop_colors[(n)*4 + 0]; \ - stop_colors[(m)*4 + 1] = stop_colors[(n)*4 + 1]; \ - stop_colors[(m)*4 + 2] = stop_colors[(n)*4 + 2]; \ - stop_colors[(m)*4 + 3] = stop_colors[(n)*4 + 3]; - - default: - case PIXMAN_REPEAT_NONE: - stop_colors[0] = 0.0; //R - stop_colors[1] = 0.0; //G - stop_colors[2] = 0.0; //B - stop_colors[3] = 0.0; //Alpha - n_stops[0] = -(float)INT_MAX; //should be small enough. - - stop_colors[0 + (count-1)*4] = 0.0; //R - stop_colors[1 + (count-1)*4] = 0.0; //G - stop_colors[2 + (count-1)*4] = 0.0; //B - stop_colors[3 + (count-1)*4] = 0.0; //Alpha - n_stops[count-1] = (float)INT_MAX; //should be large enough. - break; - case PIXMAN_REPEAT_NORMAL: - REPEAT_FILL_STOPS(0, count - 2); - n_stops[0] = n_stops[count-2] - 1.0; - - REPEAT_FILL_STOPS(count - 1, 1); - n_stops[count-1] = n_stops[1] + 1.0; - break; - case PIXMAN_REPEAT_REFLECT: - REPEAT_FILL_STOPS(0, 1); - n_stops[0] = -n_stops[1]; - - REPEAT_FILL_STOPS(count - 1, count - 2); - n_stops[count-1] = 1.0 + 1.0 - n_stops[count-2]; - break; - case PIXMAN_REPEAT_PAD: - REPEAT_FILL_STOPS(0, 1); - n_stops[0] = -(float)INT_MAX; - - REPEAT_FILL_STOPS(count - 1, count - 2); - n_stops[count-1] = (float)INT_MAX; - break; -#undef REPEAT_FILL_STOPS - } - - for (i = 0; i < count; i++) { - DEBUGF("n_stops[%d] = %f, color = r:%f g:%f b:%f a:%f\n", - i, n_stops[i], - stop_colors[i*4], stop_colors[i*4+1], - stop_colors[i*4+2], stop_colors[i*4+3]); - } - - return count; -} - -static PicturePtr -_glamor_generate_radial_gradient_picture(ScreenPtr screen, - PicturePtr src_picture, - int x_source, int y_source, - int width, int height, - PictFormatShort format) -{ - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - PicturePtr dst_picture = NULL; - PixmapPtr pixmap = NULL; - GLint gradient_prog = 0; - int error; - float tex_vertices[8]; - int stops_count; - int count = 0; - GLfloat *stop_colors = NULL; - GLfloat *n_stops = NULL; - GLfloat xscale, yscale; - float vertices[8]; - float transform_mat[3][3]; - static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0}}; - GLfloat stop_colors_st[RADIAL_SMALL_STOPS*4]; - GLfloat n_stops_st[RADIAL_SMALL_STOPS]; - GLfloat A_value; - GLfloat cxy[4]; - float c1x, c1y, c2x, c2y, r1, r2; - - GLint transform_mat_uniform_location; - GLint repeat_type_uniform_location; - GLint n_stop_uniform_location; - GLint stops_uniform_location; - GLint stop_colors_uniform_location; - GLint stop0_uniform_location; - GLint stop1_uniform_location; - GLint stop2_uniform_location; - GLint stop3_uniform_location; - GLint stop4_uniform_location; - GLint stop5_uniform_location; - GLint stop6_uniform_location; - GLint stop7_uniform_location; - GLint stop_color0_uniform_location; - GLint stop_color1_uniform_location; - GLint stop_color2_uniform_location; - GLint stop_color3_uniform_location; - GLint stop_color4_uniform_location; - GLint stop_color5_uniform_location; - GLint stop_color6_uniform_location; - GLint stop_color7_uniform_location; - GLint A_value_uniform_location; - GLint c1_uniform_location; - GLint r1_uniform_location; - GLint c2_uniform_location; - GLint r2_uniform_location; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - /* Create a pixmap with VBO. */ - pixmap = glamor_create_pixmap(screen, - width, height, - PIXMAN_FORMAT_DEPTH(format), - 0); - if (!pixmap) - goto GRADIENT_FAIL; - - dst_picture = CreatePicture(0, &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), format), - 0, 0, serverClient, &error); - - /* Release the reference, picture will hold the last one. */ - glamor_destroy_pixmap(pixmap); - - if (!dst_picture) - goto GRADIENT_FAIL; - - ValidatePicture(dst_picture); - - stops_count = src_picture->pSourcePict->radial.nstops + 2; - - /* Because the max value of nstops is unkown, so create a program - when nstops > LINEAR_LARGE_STOPS.*/ - if (stops_count <= RADIAL_SMALL_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][0]; - } else if (stops_count <= RADIAL_LARGE_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][1]; - } else { - _glamor_create_radial_gradient_program(screen, src_picture->pSourcePict->linear.nstops + 2, 1); - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]; - } - - /* Bind all the uniform vars .*/ - transform_mat_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); - repeat_type_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); - n_stop_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "n_stop"); - A_value_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "A_value"); - repeat_type_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); - c1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "c1"); - r1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "r1"); - c2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "c2"); - r2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "r2"); - - if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) { - stop0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop0"); - stop1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop1"); - stop2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop2"); - stop3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop3"); - stop4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop4"); - stop5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop5"); - stop6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop6"); - stop7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop7"); - - stop_color0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); - stop_color1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); - stop_color2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); - stop_color3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); - stop_color4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); - stop_color5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); - stop_color6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); - stop_color7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); - } else { - stops_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stops"); - stop_colors_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); - } - - dispatch->glUseProgram(gradient_prog); - - dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); - - - if (src_picture->transform) { - _glamor_gradient_convert_trans_matrix(src_picture->transform, - transform_mat, - width, height, 0); - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &transform_mat[0][0]); - } else { - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &identity_mat[0][0]); - } - - if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, - &xscale, &yscale, x_source, y_source, - vertices, tex_vertices, 0)) - goto GRADIENT_FAIL; - - /* Set all the stops and colors to shader. */ - if (stops_count > RADIAL_SMALL_STOPS) { - stop_colors = malloc(4 * stops_count * sizeof(float)); - if (stop_colors == NULL) { - ErrorF("Failed to allocate stop_colors memory.\n"); - goto GRADIENT_FAIL; - } - - n_stops = malloc(stops_count * sizeof(float)); - if (n_stops == NULL) { - ErrorF("Failed to allocate n_stops memory.\n"); - goto GRADIENT_FAIL; - } - } else { - stop_colors = stop_colors_st; - n_stops = n_stops_st; - } - - count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, - stop_colors, n_stops); - - if (src_picture->pSourcePict->linear.nstops + 2 <= RADIAL_SMALL_STOPS) { - int j = 0; - dispatch->glUniform4f(stop_color0_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color1_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color2_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color3_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color4_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color5_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color6_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color7_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - - j = 0; - dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); - dispatch->glUniform1i(n_stop_uniform_location, count); - } else { - dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); - dispatch->glUniform1fv(stops_uniform_location, count, n_stops); - dispatch->glUniform1i(n_stop_uniform_location, count); - } - - c1x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.x); - c1y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.y); - c2x = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.x); - c2y = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.y); - - r1 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.radius); - r2 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.radius); - - - cxy[0] = c1x; - cxy[1] = c1y; - dispatch->glUniform2fv(c1_uniform_location, 1, cxy); - dispatch->glUniform1f(r1_uniform_location, r1); - - cxy[0] = c2x; - cxy[1] = c2y; - dispatch->glUniform2fv(c2_uniform_location, 1, cxy); - dispatch->glUniform1f(r2_uniform_location, r2); - - A_value = (c2x - c1x) * (c2x - c1x) + (c2y - c1y) * (c2y - c1y) - (r2 - r1) * (r2 - r1); - dispatch->glUniform1f(A_value_uniform_location, A_value); - - DEBUGF("C1:(%f, %f) R1:%f\nC2:(%f, %f) R2:%f\nA = %f\n", - c1x, c1y, r1, c2x, c2y, r2, A_value); - - glamor_emit_composite_rect(screen, tex_vertices, NULL, vertices); - - if (glamor_priv->render_nr_verts) { - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); - else { - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - dispatch->glBufferData(GL_ARRAY_BUFFER, - glamor_priv->vbo_offset, - glamor_priv->vb, GL_DYNAMIC_DRAW); - } - - dispatch->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL); - } - - - /* Do the clear logic.*/ - if (stops_count > RADIAL_SMALL_STOPS) { - free(n_stops); - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - - glamor_put_dispatch(glamor_priv); - return dst_picture; - -GRADIENT_FAIL: - if (dst_picture) { - FreePicture(dst_picture, 0); - } - - if (stops_count > RADIAL_SMALL_STOPS) { - if (n_stops) - free(n_stops); - if (stop_colors) - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - glamor_put_dispatch(glamor_priv); - return NULL; -} - -static PicturePtr -_glamor_generate_linear_gradient_picture(ScreenPtr screen, - PicturePtr src_picture, - int x_source, int y_source, - int width, int height, - PictFormatShort format) -{ - glamor_screen_private *glamor_priv; - glamor_gl_dispatch *dispatch; - PicturePtr dst_picture = NULL; - PixmapPtr pixmap = NULL; - GLint gradient_prog = 0; - int error; - float pt_distance; - float p1_distance; - GLfloat cos_val; - float tex_vertices[8]; - int stops_count; - GLfloat *stop_colors = NULL; - GLfloat *n_stops = NULL; - int count = 0; - float slope; - GLfloat xscale, yscale; - GLfloat pt1[4], pt2[4]; - float vertices[8]; - float transform_mat[3][3]; - static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, - {0.0, 1.0, 0.0}, - {0.0, 0.0, 1.0}}; - GLfloat stop_colors_st[LINEAR_SMALL_STOPS*4]; - GLfloat n_stops_st[LINEAR_SMALL_STOPS]; - - GLint transform_mat_uniform_location; - GLint pt1_uniform_location; - GLint pt2_uniform_location; - GLint n_stop_uniform_location; - GLint stops_uniform_location; - GLint stop0_uniform_location; - GLint stop1_uniform_location; - GLint stop2_uniform_location; - GLint stop3_uniform_location; - GLint stop4_uniform_location; - GLint stop5_uniform_location; - GLint stop6_uniform_location; - GLint stop7_uniform_location; - GLint stop_colors_uniform_location; - GLint stop_color0_uniform_location; - GLint stop_color1_uniform_location; - GLint stop_color2_uniform_location; - GLint stop_color3_uniform_location; - GLint stop_color4_uniform_location; - GLint stop_color5_uniform_location; - GLint stop_color6_uniform_location; - GLint stop_color7_uniform_location; - GLint pt_slope_uniform_location; - GLint repeat_type_uniform_location; - GLint hor_ver_uniform_location; - GLint cos_val_uniform_location; - GLint p1_distance_uniform_location; - GLint pt_distance_uniform_location; - - glamor_priv = glamor_get_screen_private(screen); - dispatch = glamor_get_dispatch(glamor_priv); - - /* Create a pixmap with VBO. */ - pixmap = glamor_create_pixmap(screen, - width, height, - PIXMAN_FORMAT_DEPTH(format), - 0); - - if (!pixmap) - goto GRADIENT_FAIL; - - dst_picture = CreatePicture(0, &pixmap->drawable, - PictureMatchFormat(screen, - PIXMAN_FORMAT_DEPTH(format), format), - 0, 0, serverClient, &error); - - /* Release the reference, picture will hold the last one. */ - glamor_destroy_pixmap(pixmap); - - if (!dst_picture) - goto GRADIENT_FAIL; - - ValidatePicture(dst_picture); - - stops_count = src_picture->pSourcePict->linear.nstops + 2; - - /* Because the max value of nstops is unkown, so create a program - when nstops > LINEAR_LARGE_STOPS.*/ - if (stops_count <= LINEAR_SMALL_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][0]; - } else if (stops_count <= LINEAR_LARGE_STOPS) { - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][1]; - } else { - _glamor_create_linear_gradient_program(screen, - src_picture->pSourcePict->linear.nstops + 2, 1); - gradient_prog = glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]; - } - - /* Bind all the uniform vars .*/ - pt1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt1"); - pt2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt2"); - n_stop_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "n_stop"); - pt_slope_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt_slope"); - repeat_type_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "repeat_type"); - hor_ver_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "hor_ver"); - transform_mat_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "transform_mat"); - cos_val_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "cos_val"); - p1_distance_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "p1_distance"); - pt_distance_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt_distance"); - - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { - stop0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop0"); - stop1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop1"); - stop2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop2"); - stop3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop3"); - stop4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop4"); - stop5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop5"); - stop6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop6"); - stop7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop7"); - - stop_color0_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color0"); - stop_color1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color1"); - stop_color2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color2"); - stop_color3_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color3"); - stop_color4_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color4"); - stop_color5_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color5"); - stop_color6_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color6"); - stop_color7_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_color7"); - } else { - stops_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stops"); - stop_colors_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "stop_colors"); - } - - dispatch->glUseProgram(gradient_prog); - - dispatch->glUniform1i(repeat_type_uniform_location, src_picture->repeatType); - - if (src_picture->transform) { - _glamor_gradient_convert_trans_matrix(src_picture->transform, - transform_mat, - width, height, 1); - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &transform_mat[0][0]); - } else { - dispatch->glUniformMatrix3fv(transform_mat_uniform_location, - 1, 1, &identity_mat[0][0]); - } - - if (!_glamor_gradient_set_pixmap_destination(screen, glamor_priv, dst_picture, - &xscale, &yscale, x_source, y_source, - vertices, tex_vertices, 1)) - goto GRADIENT_FAIL; - - /* Normalize the PTs. */ - glamor_set_normalize_pt(xscale, yscale, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.x), - x_source, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.y), - y_source, - glamor_priv->yInverted, - pt1); - dispatch->glUniform4fv(pt1_uniform_location, 1, pt1); - DEBUGF("pt1:(%f %f)\n", pt1[0], pt1[1]); - - glamor_set_normalize_pt(xscale, yscale, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.x), - x_source, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.y), - y_source, - glamor_priv->yInverted, - pt2); - dispatch->glUniform4fv(pt2_uniform_location, 1, pt2); - DEBUGF("pt2:(%f %f)\n", pt2[0], pt2[1]); - - /* Set all the stops and colors to shader. */ - if (stops_count > LINEAR_SMALL_STOPS) { - stop_colors = malloc(4 * stops_count * sizeof(float)); - if (stop_colors == NULL) { - ErrorF("Failed to allocate stop_colors memory.\n"); - goto GRADIENT_FAIL; - } - - n_stops = malloc(stops_count * sizeof(float)); - if (n_stops == NULL) { - ErrorF("Failed to allocate n_stops memory.\n"); - goto GRADIENT_FAIL; - } - } else { - stop_colors = stop_colors_st; - n_stops = n_stops_st; - } - - count = _glamor_gradient_set_stops(src_picture, &src_picture->pSourcePict->gradient, - stop_colors, n_stops); - - if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) { - int j = 0; - dispatch->glUniform4f(stop_color0_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color1_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color2_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color3_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color4_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color5_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color6_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - j++; - dispatch->glUniform4f(stop_color7_uniform_location, stop_colors[4*j+0], stop_colors[4*j+1], - stop_colors[4*j+2], stop_colors[4*j+3]); - - j = 0; - dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]); - dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]); - - dispatch->glUniform1i(n_stop_uniform_location, count); - } else { - dispatch->glUniform4fv(stop_colors_uniform_location, count, stop_colors); - dispatch->glUniform1fv(stops_uniform_location, count, n_stops); - dispatch->glUniform1i(n_stop_uniform_location, count); - } - - if ((pt2[1] - pt1[1]) / yscale < 1.0) { // The horizontal case. - dispatch->glUniform1i(hor_ver_uniform_location, 1); - DEBUGF("p1.x: %f, p2.x: %f, enter the horizontal case\n", pt1[1], pt2[1]); - - p1_distance = pt1[0]; - pt_distance = (pt2[0] - p1_distance); - dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); - dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); - } else if ((pt2[0] - pt1[0]) / xscale < 1.0) { //The vertical case. - dispatch->glUniform1i(hor_ver_uniform_location, 2); - DEBUGF("p1.y: %f, p2.y: %f, enter the vertical case\n", pt1[0], pt2[0]); - - p1_distance = pt1[1]; - pt_distance = (pt2[1] - p1_distance); - dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); - dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); - } else { - /* The slope need to compute here. In shader, the viewport set will change - the orginal slope and the slope which is vertical to it will not be correct.*/ - slope = - (float)(src_picture->pSourcePict->linear.p2.x - src_picture->pSourcePict->linear.p1.x) / - (float)(src_picture->pSourcePict->linear.p2.y - src_picture->pSourcePict->linear.p1.y); - slope = slope * yscale / xscale; - dispatch->glUniform1f(pt_slope_uniform_location, slope); - dispatch->glUniform1i(hor_ver_uniform_location, 0); - - cos_val = sqrt(1.0 / (slope * slope + 1.0)); - dispatch->glUniform1f(cos_val_uniform_location, cos_val); - - p1_distance = (pt1[1] - pt1[0] * slope) * cos_val; - pt_distance = (pt2[1] - pt2[0] * slope) * cos_val - p1_distance; - dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); - dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); - } - - /* set the transform matrix. */ /* Now rendering. */ - glamor_emit_composite_rect(screen, tex_vertices, NULL, vertices); - - if (glamor_priv->render_nr_verts) { - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) - dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); - else { - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); - dispatch->glBufferData(GL_ARRAY_BUFFER, - glamor_priv->vbo_offset, - glamor_priv->vb, GL_DYNAMIC_DRAW); - } - - dispatch->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL); - } - - /* Do the clear logic.*/ - if (stops_count > LINEAR_SMALL_STOPS) { - free(n_stops); - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - - glamor_put_dispatch(glamor_priv); - return dst_picture; - -GRADIENT_FAIL: - if (dst_picture) { - FreePicture(dst_picture, 0); - } - - if (stops_count > LINEAR_SMALL_STOPS) { - if (n_stops) - free(n_stops); - if (stop_colors) - free(stop_colors); - } - - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); - dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - dispatch->glUseProgram(0); - glamor_put_dispatch(glamor_priv); - return NULL; -} -#undef LINEAR_DEFAULT_STOPS -#endif - static PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr source, @@ -2933,10 +1355,10 @@ glamor_convert_gradient_picture(ScreenPtr screen, #ifdef GLAMOR_GRADIENT_SHADER if (!source->pDrawable) { if (source->pSourcePict->type == SourcePictTypeLinear) { - dst = _glamor_generate_linear_gradient_picture(screen, + dst = glamor_generate_linear_gradient_picture(screen, source, x_source, y_source, width, height, format); } else if (source->pSourcePict->type == SourcePictTypeRadial) { - dst = _glamor_generate_radial_gradient_picture(screen, + dst = glamor_generate_radial_gradient_picture(screen, source, x_source, y_source, width, height, format); } @@ -3021,6 +1443,11 @@ _glamor_composite(CARD8 op, x_temp_mask = x_mask; y_temp_mask = y_mask; + DEBUGF("Composite Src: (%d, %d)\n" + " Mask: (%d, %d)\n" + " to dst: (%d, %d), size: %d X %d \n", + x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ From 09de37ec1c0543c8073f934274c84b3b7d5f31ae Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 15 May 2012 10:07:35 +0800 Subject: [PATCH 376/462] Fix a bugy macro definition. The macro like "#define LINEAR_SMALL_STOPS 6 + 2" causes the problem. When use it to define like "GLfloat stop_colors_st[LINEAR_SMALL_STOPS*4];" The array is small than what we supposed it to be. Cause memory corruption problem and cause the bug of render wrong result. Fix it. Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_gradient.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index f1c36af69..165d211b9 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -34,11 +34,11 @@ #ifdef RENDER -#define LINEAR_SMALL_STOPS 6 + 2 -#define LINEAR_LARGE_STOPS 16 + 2 +#define LINEAR_SMALL_STOPS (6 + 2) +#define LINEAR_LARGE_STOPS (16 + 2) -#define RADIAL_SMALL_STOPS 6 + 2 -#define RADIAL_LARGE_STOPS 16 + 2 +#define RADIAL_SMALL_STOPS (6 + 2) +#define RADIAL_LARGE_STOPS (16 + 2) #ifdef GLAMOR_GRADIENT_SHADER From 41aa93c393c8760aae357725db63fa4a8f798557 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 15 May 2012 10:07:46 +0800 Subject: [PATCH 377/462] Fix the problem of set the same stop several times. Some gradient set the stops at the same position, for example: firstly 0.5 to red color and then set 0.5 to blue. This kind of setting will cause the shader work not correctly because the percentage caculating need to use the stop[i] - stop[i-1] as dividend. The previous patch we just kill some stop if the distance between them is 0. But this cause the problem that the color for next stop is wrong. We now modify to handle it in the shader to avoid the 0 as dividend. Reviewed-by: Zhigang Gong Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_gradient.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index 165d211b9..b24dc9f23 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -67,9 +67,12 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar " break; \n" " }\n" " \n" - " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n" " if(stops[i] - stops[i-1] > 2.0)\n" " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. + " else if(stops[i] - stops[i-1] < 0.000001)\n" + " percentage = 0.0;\n" + " else \n" + " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n" " new_alpha = percentage * stop_colors[i].a + \n" " (1.0-percentage) * stop_colors[i-1].a; \n" " gradient_color = vec4((percentage * stop_colors[i].rgb \n" @@ -116,58 +119,53 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar " stop_color_after = stop_color0;\n" " stop_after = stop0;\n" " stop_before = stop0;\n" - " percentage = 0.0;\n" " } else if((stop_len < stop1) && (n_stop >= 2)) {\n" " stop_color_before = stop_color0;\n" " stop_color_after = stop_color1;\n" " stop_after = stop1;\n" " stop_before = stop0;\n" - " percentage = (stop_len - stop0)/(stop1 - stop0);\n" " } else if((stop_len < stop2) && (n_stop >= 3)) {\n" " stop_color_before = stop_color1;\n" " stop_color_after = stop_color2;\n" " stop_after = stop2;\n" " stop_before = stop1;\n" - " percentage = (stop_len - stop1)/(stop2 - stop1);\n" " } else if((stop_len < stop3) && (n_stop >= 4)){\n" " stop_color_before = stop_color2;\n" " stop_color_after = stop_color3;\n" " stop_after = stop3;\n" " stop_before = stop2;\n" - " percentage = (stop_len - stop2)/(stop3 - stop2);\n" " } else if((stop_len < stop4) && (n_stop >= 5)){\n" " stop_color_before = stop_color3;\n" " stop_color_after = stop_color4;\n" " stop_after = stop4;\n" " stop_before = stop3;\n" - " percentage = (stop_len - stop3)/(stop4 - stop3);\n" " } else if((stop_len < stop5) && (n_stop >= 6)){\n" " stop_color_before = stop_color4;\n" " stop_color_after = stop_color5;\n" " stop_after = stop5;\n" " stop_before = stop4;\n" - " percentage = (stop_len - stop4)/(stop5 - stop4);\n" " } else if((stop_len < stop6) && (n_stop >= 7)){\n" " stop_color_before = stop_color5;\n" " stop_color_after = stop_color6;\n" " stop_after = stop6;\n" " stop_before = stop5;\n" - " percentage = (stop_len - stop5)/(stop6 - stop5);\n" " } else if((stop_len < stop7) && (n_stop >= 8)){\n" " stop_color_before = stop_color6;\n" " stop_color_after = stop_color7;\n" " stop_after = stop7;\n" " stop_before = stop6;\n" - " percentage = (stop_len - stop6)/(stop7 - stop6);\n" " } else {\n" " stop_color_before = stop_color7;\n" " stop_color_after = stop_color7;\n" " stop_after = stop7;\n" " stop_before = stop7;\n" - " percentage = 0.0;\n" " }\n" " if(stop_after - stop_before > 2.0)\n" " percentage = 0.0;\n"//For comply with pixman, walker->stepper overflow. + " else if(stop_after - stop_before < 0.000001)\n" + " percentage = 0.0;\n" + " else \n" + " percentage = (stop_len - stop_before)/(stop_after - stop_before);\n" " new_alpha = percentage * stop_color_after.a + \n" " (1.0-percentage) * stop_color_before.a; \n" " gradient_color = vec4((percentage * stop_color_after.rgb \n" @@ -880,13 +878,6 @@ _glamor_gradient_set_stops(PicturePtr src_picture, PictGradient * pgradient, int count = 1; for (i = 0; i < pgradient->nstops; i++) { - /* We find some gradient picture set the stops at the same percentage, which - will cause the shader problem because the (stops[i] - stops[i-1]) will - be used as divisor. We just keep the later one if stops[i] == stops[i-1] */ - if (i < pgradient->nstops - 1 - && pgradient->stops[i].x == pgradient->stops[i+1].x) - continue; - stop_colors[count*4] = pixman_fixed_to_double( pgradient->stops[i].color.red); stop_colors[count*4+1] = pixman_fixed_to_double( From 553910d08b93ef80cc25fcbfd7876726778bc655 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 15 May 2012 10:07:55 +0800 Subject: [PATCH 378/462] Fix the problem of vertical and horizontal case error in linear gradient. 1. The vertical and horizontal judgement in linear gradient have problem when p1 point and p2 point distance is very small but the gradient pict have a transform matrix which will convert the X Y coordinates to small values. So the judgement is not suitable. Because this judgement's purpose is to assure the divisor not to be zero, so we simply it to enter horizontal judgement when p1 and p2's Y is same. Vertical case is deleted. 2. Delete the unused p1 p2 uniform variable. Reviewed-by: Zhigang Gong Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_gradient.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index b24dc9f23..8e1d06a6f 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -491,8 +491,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy "uniform mat3 transform_mat;\n" "uniform int repeat_type;\n" "uniform int hor_ver;\n" - "uniform vec4 pt1;\n" - "uniform vec4 pt2;\n" "uniform float pt_slope;\n" "uniform float cos_val;\n" "uniform float p1_distance;\n" @@ -529,10 +527,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy " distance = source_texture_trans.x;\n" " _p1_distance = p1_distance * source_texture_trans.z;\n" " _pt_distance = pt_distance * source_texture_trans.z;\n" - " } else if (hor_ver == 2) {\n"//vertical case. - " distance = source_texture_trans.y;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" " } \n" " \n" " distance = distance - _p1_distance; \n" @@ -1366,10 +1360,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, } /* Bind all the uniform vars .*/ - pt1_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt1"); - pt2_uniform_location = - dispatch->glGetUniformLocation(gradient_prog, "pt2"); n_stop_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "n_stop"); pt_slope_uniform_location = @@ -1542,22 +1532,16 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, dispatch->glUniform1i(n_stop_uniform_location, count); } - if (abs((pt2[1] - pt1[1]) / yscale) < 1.0) { // The horizontal case. + if (src_picture->pSourcePict->linear.p2.y == + src_picture->pSourcePict->linear.p1.y) { // The horizontal case. dispatch->glUniform1i(hor_ver_uniform_location, 1); - DEBUGF("p1.x: %f, p2.x: %f, enter the horizontal case\n", pt1[1], pt2[1]); + DEBUGF("p1.y: %f, p2.y: %f, enter the horizontal case\n", + pt1[1], pt2[1]); p1_distance = pt1[0]; pt_distance = (pt2[0] - p1_distance); dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); - } else if (abs((pt2[0] - pt1[0]) / xscale) < 1.0) { //The vertical case. - dispatch->glUniform1i(hor_ver_uniform_location, 2); - DEBUGF("p1.y: %f, p2.y: %f, enter the vertical case\n", pt1[0], pt2[0]); - - p1_distance = pt1[1]; - pt_distance = (pt2[1] - p1_distance); - dispatch->glUniform1f(p1_distance_uniform_location, p1_distance); - dispatch->glUniform1f(pt_distance_uniform_location, pt_distance); } else { /* The slope need to compute here. In shader, the viewport set will change the orginal slope and the slope which is vertical to it will not be correct.*/ From 4c174f4c9ce1514ef226e9de97e5c87a46a75524 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 15 May 2012 10:08:03 +0800 Subject: [PATCH 379/462] Fix the problem of x_source and y_source causing radial error The x_source and y_source cause some problem in gradient. The old way to handle it by recaulate P1 P2 to minus the x_source and y_source, but this causes problem in radial shader. Now we modify the manner to set the texture coordinates: (x_source, y_source) --> (x_source + width, y_source + height) to handle all the cases. Reviewed-by: Zhigang Gong Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_gradient.c | 43 ++++++++---------- glamor/glamor_utils.h | 95 ++++++++++++++++++++++------------------ 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index 8e1d06a6f..ab2c2ed2f 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -814,14 +814,16 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, if (tex_normalize) { glamor_set_normalize_tcoords(*xscale, *yscale, - 0, 0, - (INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), + x_source, y_source, + (INT16)(dst_picture->pDrawable->width + x_source), + (INT16)(dst_picture->pDrawable->height + y_source), glamor_priv->yInverted, tex_vertices); } else { - glamor_set_tcoords(0, 0, - (INT16)(dst_picture->pDrawable->width), + glamor_set_tcoords((INT16)(dst_picture->pDrawable->width), (INT16)(dst_picture->pDrawable->height), + x_source, y_source, + (INT16)(dst_picture->pDrawable->width) + x_source, + (INT16)(dst_picture->pDrawable->height) + y_source, glamor_priv->yInverted, tex_vertices); } @@ -1201,14 +1203,11 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen, r1 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.radius); r2 = (float)pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.radius); - - cxy[0] = c1x; - cxy[1] = c1y; + glamor_set_circle_centre(width, height, c1x, c1y, glamor_priv->yInverted, cxy); dispatch->glUniform2fv(c1_uniform_location, 1, cxy); dispatch->glUniform1f(r1_uniform_location, r1); - cxy[0] = c2x; - cxy[1] = c2y; + glamor_set_circle_centre(width, height, c2x, c2y, glamor_priv->yInverted, cxy); dispatch->glUniform2fv(c2_uniform_location, 1, cxy); dispatch->glUniform1f(r2_uniform_location, r2); @@ -1282,7 +1281,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, int count = 0; float slope; GLfloat xscale, yscale; - GLfloat pt1[4], pt2[4]; + GLfloat pt1[2], pt2[2]; float vertices[8]; float transform_mat[3][3]; static const float identity_mat[3][3] = {{1.0, 0.0, 0.0}, @@ -1292,8 +1291,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, GLfloat n_stops_st[LINEAR_SMALL_STOPS]; GLint transform_mat_uniform_location = 0; - GLint pt1_uniform_location = 0; - GLint pt2_uniform_location = 0; GLint n_stop_uniform_location = 0; GLint stops_uniform_location = 0; GLint stop0_uniform_location = 0; @@ -1441,24 +1438,20 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen, /* Normalize the PTs. */ glamor_set_normalize_pt(xscale, yscale, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.x), - x_source, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p1.y), - y_source, + pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x), + pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y), glamor_priv->yInverted, pt1); - dispatch->glUniform4fv(pt1_uniform_location, 1, pt1); - DEBUGF("pt1:(%f %f)\n", pt1[0], pt1[1]); + DEBUGF("pt1:(%f, %f) ---> (%f %f)\n", pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x), + pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y), pt1[0], pt1[1]); glamor_set_normalize_pt(xscale, yscale, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.x), - x_source, - pixman_fixed_to_int(src_picture->pSourcePict->linear.p2.y), - y_source, + pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x), + pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y), glamor_priv->yInverted, pt2); - dispatch->glUniform4fv(pt2_uniform_location, 1, pt2); - DEBUGF("pt2:(%f %f)\n", pt2[0], pt2[1]); + DEBUGF("pt2:(%f, %f) ---> (%f %f)\n", pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x), + pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y), pt2[0], pt2[1]); /* Set all the stops and colors to shader. */ if (stops_count > LINEAR_SMALL_STOPS) { diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 8dad2dfd6..4af6739dd 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -143,54 +143,65 @@ (vertices)[7] = (vertices)[5]; \ } while(0) -#define glamor_set_tcoords(x1, y1, x2, y2, yInverted, vertices) \ - do { \ - (vertices)[0] = (x1); \ - (vertices)[2] = (x2); \ - (vertices)[4] = (vertices)[2]; \ - (vertices)[6] = (vertices)[0]; \ - if (yInverted) { \ - (vertices)[1] = (y1); \ - (vertices)[5] = (y2); \ - } \ - else { \ - (vertices)[1] = (y2); \ - (vertices)[5] = (y1); \ - } \ - (vertices)[3] = (vertices)[1]; \ - (vertices)[7] = (vertices)[5]; \ +#define glamor_set_tcoords(width, height, x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = (x1); \ + (vertices)[2] = (x2); \ + (vertices)[4] = (vertices)[2]; \ + (vertices)[6] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = (y1); \ + (vertices)[5] = (y2); \ + } \ + else { \ + (vertices)[1] = height - (y2); \ + (vertices)[5] = height - (y1); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[7] = (vertices)[5]; \ } while(0) #define glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, \ yInverted, vertices) \ - do { \ - (vertices)[0] = v_from_x_coord_x(xscale, x1); \ - (vertices)[2] = v_from_x_coord_x(xscale, x2); \ - (vertices)[4] = (vertices)[2]; \ - (vertices)[6] = (vertices)[0]; \ - if (yInverted) { \ - (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ - (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2); \ - } \ - else { \ - (vertices)[1] = v_from_x_coord_y(yscale, y1); \ - (vertices)[5] = v_from_x_coord_y(yscale, y2); \ - } \ - (vertices)[3] = (vertices)[1]; \ - (vertices)[7] = (vertices)[5]; \ - } while(0) + do { \ + (vertices)[0] = v_from_x_coord_x(xscale, x1); \ + (vertices)[2] = v_from_x_coord_x(xscale, x2); \ + (vertices)[4] = (vertices)[2]; \ + (vertices)[6] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ + (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2); \ + } \ + else { \ + (vertices)[1] = v_from_x_coord_y(yscale, y1); \ + (vertices)[5] = v_from_x_coord_y(yscale, y2); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[7] = (vertices)[5]; \ + } while(0) -#define glamor_set_normalize_pt(xscale, yscale, x, x_start, y, y_start, \ - yInverted, pt) \ - do { \ - (pt)[0] = t_from_x_coord_x(xscale, x - x_start); \ - if (yInverted) { \ - (pt)[1] = t_from_x_coord_y_inverted(yscale, y - y_start); \ - } else { \ - (pt)[1] = t_from_x_coord_y(yscale, y - y_start); \ - } \ - (pt)[2] = (pt)[3] = 0.0; \ +#define glamor_set_normalize_pt(xscale, yscale, x, y, \ + yInverted, pt) \ + do { \ + (pt)[0] = t_from_x_coord_x(xscale, x); \ + if (yInverted) { \ + (pt)[1] = t_from_x_coord_y_inverted(yscale, y); \ + } else { \ + (pt)[1] = t_from_x_coord_y(yscale, y); \ + } \ + } while(0) + +#define glamor_set_circle_centre(width, height, x, y, \ + yInverted, c) \ + do { \ + (c)[0] = (float)x; \ + if (yInverted) { \ + (c)[1] = (float)y; \ + } else { \ + (c)[1] = (float)height - (float)y; \ + } \ } while(0) inline static void From ace35e408cd7a79c5215bbd0f14b624d8d949e34 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 01:02:30 +0800 Subject: [PATCH 380/462] glamor_largepixmap: first commit for large pixmap. This is the first commit to add support for large pixmap. The large here means a pixmap is larger than the texutre's size limitation thus can't fit into one single texutre. The previous implementation will simply fallback to use a in memory pixmap to contain the large pixmap which is very slow in practice. The basic idea here is to use an array of texture to hold the large pixmap. And when we need to get a specific area of the pixmap, we just need to compute/clip the correct region and find the corresponding fbo. We need to implement some auxiliary routines to clip every rendering operations into small pieces which can fit into one texture. The complex part is the transformation/repeat/repeatReflect and repeat pad and their comination. We will support all of them step by step. This commit just add some necessary data structure to represent the large pixmap, and doesn't change any rendering process. This commit doesn't add real large pixmap support. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 16 +-- glamor/glamor.h | 4 +- glamor/glamor_copyarea.c | 15 +-- glamor/glamor_core.c | 18 ++-- glamor/glamor_debug.h | 4 +- glamor/glamor_fbo.c | 34 +++---- glamor/glamor_fill.c | 2 +- glamor/glamor_gradient.c | 4 +- glamor/glamor_picture.c | 10 +- glamor/glamor_pixmap.c | 80 +++++++-------- glamor/glamor_priv.h | 185 +++++++++++++++++++++++++++++++++-- glamor/glamor_putimage.c | 6 +- glamor/glamor_render.c | 16 +-- glamor/glamor_tile.c | 11 ++- glamor/glamor_utils.h | 204 ++++++++++++++++++++++++++++----------- 15 files changed, 439 insertions(+), 170 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 6b6fa0bec..a22f445d4 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -73,8 +73,8 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) if (pixmap_priv == NULL) { pixmap_priv = calloc(sizeof(*pixmap_priv), 1); glamor_set_pixmap_private(pixmap, pixmap_priv); - pixmap_priv->container = pixmap; - pixmap_priv->glamor_priv = glamor_priv; + pixmap_priv->base.pixmap = pixmap; + pixmap_priv->base.glamor_priv = glamor_priv; } pixmap_priv->type = type; } @@ -91,7 +91,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) glamor_priv = glamor_get_screen_private(screen); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv->fbo) { + if (pixmap_priv->base.fbo) { fbo = glamor_pixmap_detach_fbo(pixmap_priv); glamor_destroy_fbo(fbo); } @@ -117,10 +117,10 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap) glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - glamor_priv->screen_fbo = pixmap_priv->fbo->fb; + glamor_priv->screen_fbo = pixmap_priv->base.fbo->fb; - pixmap_priv->fbo->width = screen_pixmap->drawable.width; - pixmap_priv->fbo->height = screen_pixmap->drawable.height; + pixmap_priv->base.fbo->width = screen_pixmap->drawable.width; + pixmap_priv->base.fbo->height = screen_pixmap->drawable.height; glamor_priv->back_pixmap = back_pixmap; } @@ -159,8 +159,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (usage == GLAMOR_CREATE_PIXMAP_MAP) type = GLAMOR_MEMORY_MAP; - pixmap_priv->container = pixmap; - pixmap_priv->glamor_priv = glamor_priv; + pixmap_priv->base.pixmap = pixmap; + pixmap_priv->base.glamor_priv = glamor_priv; pixmap_priv->type = type; gl_iformat_for_depth(depth, &format); diff --git a/glamor/glamor.h b/glamor/glamor.h index c2db86a3a..fe3e4f849 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -55,7 +55,9 @@ typedef enum glamor_pixmap_type { GLAMOR_TEXTURE_DRM, GLAMOR_SEPARATE_TEXTURE, GLAMOR_DRM_ONLY, - GLAMOR_TEXTURE_ONLY + GLAMOR_TEXTURE_ONLY, + GLAMOR_TEXTURE_LARGE, + GLAMOR_TEXTURE_PACK } glamor_pixmap_type_t; #define GLAMOR_EGL_EXTERNAL_BUFFER 3 diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 356e0f9b6..84a449c8c 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -75,7 +75,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, - src_pixmap_priv->fbo->fb); + src_pixmap_priv->base.fbo->fb); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, @@ -164,7 +164,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, return FALSE; } - if (!src_pixmap_priv || !src_pixmap_priv->gl_fbo) { + if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); return FALSE; @@ -209,7 +209,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->fbo->tex); + src_pixmap_priv->base.fbo->tex); #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); dispatch->glTexParameteri(GL_TEXTURE_2D, @@ -239,7 +239,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, for (i = 0; i < nbox; i++) { - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, + glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, + dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, box[i].x2 + dst_x_off, @@ -247,7 +248,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_xscale, + glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, src_yscale, box[i].x1 + dx, box[i].y1 + dy, @@ -320,7 +321,7 @@ _glamor_copy_n_to_n(DrawablePtr src, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - if (src_pixmap_priv->fbo && src_pixmap_priv->fbo->fb == dst_pixmap_priv->fbo->fb) { + if (src_pixmap_priv->base.fbo && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { int x_shift = abs(src_x_off - dx - dst_x_off); int y_shift = abs(src_y_off - dy - dst_y_off); for (i = 0; i < nbox; i++) { @@ -333,7 +334,7 @@ _glamor_copy_n_to_n(DrawablePtr src, } #ifndef GLAMOR_GLES2 if ((overlaped - || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex) + || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { ret = TRUE; diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 009a0899b..8ba3347d1 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -43,9 +43,9 @@ glamor_get_drawable_location(const DrawablePtr drawable) 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) + if (pixmap_priv == NULL || pixmap_priv->base.gl_fbo == 0) return 'm'; - if (pixmap_priv->fbo->fb == glamor_priv->screen_fbo) + if (pixmap_priv->base.fbo->fb == glamor_priv->screen_fbo) return 's'; else return 'f'; @@ -327,7 +327,7 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) glamor_restore_pixmap_to_texture(pixmap); } - if (pixmap_priv->fbo->pbo != 0 && pixmap_priv->fbo->pbo_valid) { + if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) { glamor_gl_dispatch *dispatch; assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); @@ -335,20 +335,20 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode) dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo); + dispatch->glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo); glamor_put_dispatch(glamor_priv); - pixmap_priv->fbo->pbo_valid = FALSE; - pixmap_priv->fbo->pbo = 0; + pixmap_priv->base.fbo->pbo_valid = FALSE; + pixmap_priv->base.fbo->pbo = 0; } else { free(pixmap->devPrivate.ptr); } if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) - pixmap->devKind = pixmap_priv->drm_stride; + pixmap->devKind = pixmap_priv->base.drm_stride; - if (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED) - pixmap_priv->gl_fbo = GLAMOR_FBO_NORMAL; + if (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED) + pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL; pixmap->devPrivate.ptr = NULL; } diff --git a/glamor/glamor_debug.h b/glamor/glamor_debug.h index 99dce041c..f0c969b11 100644 --- a/glamor/glamor_debug.h +++ b/glamor/glamor_debug.h @@ -107,8 +107,10 @@ AbortServer(void) _glamor_priv_->delayed_fallback_string); \ _glamor_priv_->delayed_fallback_pending = 0; } } while(0) -#define DEBUGF(str, ...) +#define DEBUGF(str, ...) do {} while(0) //#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) +#define DEBUGRegionPrint(x) do {} while (0) +//#define DEBUGRegionPrint RegionPrint #endif diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index f4e02b205..5337149cd 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -412,11 +412,11 @@ glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) if (pixmap_priv == NULL) return NULL; - fbo = pixmap_priv->fbo; + fbo = pixmap_priv->base.fbo; if (fbo == NULL) return NULL; - pixmap_priv->fbo = NULL; + pixmap_priv->base.fbo = NULL; return fbo; } @@ -434,25 +434,25 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) pixmap_priv = calloc(1, sizeof(*pixmap_priv)); dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, pixmap_priv); - pixmap_priv->container = pixmap; - pixmap_priv->glamor_priv = glamor_priv; + pixmap_priv->base.pixmap = pixmap; + pixmap_priv->base.glamor_priv = glamor_priv; pixmap_priv->type = GLAMOR_MEMORY; } - if (pixmap_priv->fbo) + if (pixmap_priv->base.fbo) return; - pixmap_priv->fbo = fbo; + pixmap_priv->base.fbo = fbo; switch (pixmap_priv->type) { case GLAMOR_TEXTURE_ONLY: case GLAMOR_TEXTURE_DRM: - pixmap_priv->gl_fbo = 1; + pixmap_priv->base.gl_fbo = 1; if (fbo->tex != 0) - pixmap_priv->gl_tex = 1; + pixmap_priv->base.gl_tex = 1; else { /* XXX For the Xephyr only, may be broken now.*/ - pixmap_priv->gl_tex = 0; + pixmap_priv->base.gl_tex = 0; } case GLAMOR_MEMORY_MAP: pixmap->devPrivate.ptr = NULL; @@ -472,7 +472,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) { + if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, @@ -484,12 +484,12 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_pixmap_attach_fbo(pixmap, fbo); } else { /* We do have a fbo, but it may lack of fb or tex. */ - if (!pixmap_priv->fbo->tex) - pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, + if (!pixmap_priv->base.fbo->tex) + pixmap_priv->base.fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, format); - if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0) - glamor_pixmap_ensure_fb(pixmap_priv->fbo); + if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->base.fbo->fb == 0) + glamor_pixmap_ensure_fb(pixmap_priv->base.fbo); } pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -504,7 +504,7 @@ glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back) front_priv = glamor_get_pixmap_private(front); back_priv = glamor_get_pixmap_private(back); - temp_fbo = front_priv->fbo; - front_priv->fbo = back_priv->fbo; - back_priv->fbo = temp_fbo; + temp_fbo = front_priv->base.fbo; + front_priv->base.fbo = back_priv->base.fbo; + back_priv->base.fbo = temp_fbo; } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 57dd69851..b63756db8 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -239,7 +239,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); - glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, + glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index ab2c2ed2f..09e33d7ce 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -806,14 +806,14 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, *xscale, *yscale, x_source, y_source, dst_picture->pDrawable->width, dst_picture->pDrawable->height); - glamor_set_normalize_vcoords(*xscale, *yscale, + glamor_set_normalize_vcoords(pixmap_priv, *xscale, *yscale, 0, 0, (INT16)(dst_picture->pDrawable->width), (INT16)(dst_picture->pDrawable->height), glamor_priv->yInverted, vertices); if (tex_normalize) { - glamor_set_normalize_tcoords(*xscale, *yscale, + glamor_set_normalize_tcoords(pixmap_priv, *xscale, *yscale, x_source, y_source, (INT16)(dst_picture->pDrawable->width + x_source), (INT16)(dst_picture->pDrawable->height + y_source), diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index a6d21f110..44e1e40d7 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -101,8 +101,8 @@ glamor_create_picture(PicturePtr picture) } } - pixmap_priv->is_picture = 1; - pixmap_priv->pict_format = picture->format; + pixmap_priv->base.is_picture = 1; + pixmap_priv->base.picture = picture; return miCreatePicture(picture); } @@ -123,8 +123,8 @@ glamor_destroy_picture(PicturePtr picture) pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv) { - pixmap_priv->is_picture = 0; - pixmap_priv->pict_format = 0; + pixmap_priv->base.is_picture = 0; + pixmap_priv->base.picture = NULL; } miDestroyPicture(picture); } @@ -133,5 +133,5 @@ void glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private * pixmap_priv) { - pixmap_priv->pict_format = picture->format; + pixmap_priv->base.picture = picture; } diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index f0c158676..fa05bed8b 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -83,9 +83,9 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo, int x0, int y0, int w void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { - glamor_set_destination_pixmap_fbo(pixmap_priv->fbo, 0, 0, - pixmap_priv->container->drawable.width, - pixmap_priv->container->drawable.height); + glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0, + pixmap_priv->base.pixmap->drawable.width, + pixmap_priv->base.pixmap->drawable.height); } int @@ -495,8 +495,8 @@ ready_to_upload: && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip) { - assert(pixmap_priv->fbo->tex); - __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex, + assert(pixmap_priv->base.fbo->tex); + __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex, format, type, x, y, w, h, bits, pbo); @@ -509,7 +509,7 @@ ready_to_upload: ptexcoords = texcoords_inv; pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale); - glamor_set_normalize_vcoords(dst_xscale, + glamor_set_normalize_vcoords(pixmap_priv, dst_xscale, dst_yscale, x, y, x + w, y + h, @@ -586,14 +586,14 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - if (pixmap_priv->fbo - && (pixmap_priv->fbo->width < pixmap->drawable.width - || pixmap_priv->fbo->height < pixmap->drawable.height)) { + if (pixmap_priv->base.fbo + && (pixmap_priv->base.fbo->width < pixmap->drawable.width + || pixmap_priv->base.fbo->height < pixmap->drawable.height)) { fbo = glamor_pixmap_detach_fbo(pixmap_priv); glamor_destroy_fbo(fbo); } - if (pixmap_priv->fbo && pixmap_priv->fbo->fb) + if (pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb) return 0; if (!(no_alpha @@ -605,8 +605,8 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int flag = GLAMOR_CREATE_FBO_NO_FBO; } - if ((flag == 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->tex) - || (flag != 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb)) + if ((flag == 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) + || (flag != 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) return 0; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) @@ -614,7 +614,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int else iformat = format; - if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) { + if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, @@ -672,10 +672,10 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap_priv = glamor_get_pixmap_private(pixmap); if (pixmap_priv - && (pixmap_priv->fbo) - && (pixmap_priv->fbo->pbo_valid)) { + && (pixmap_priv->base.fbo) + && (pixmap_priv->base.fbo->pbo_valid)) { data = NULL; - pbo = pixmap_priv->fbo->pbo; + pbo = pixmap_priv->base.fbo->pbo; } else { data = pixmap->devPrivate.ptr; pbo = 0; @@ -737,7 +737,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe temp_xscale = 1.0 / w; temp_yscale = 1.0 / h; - glamor_set_normalize_vcoords(temp_xscale, + glamor_set_normalize_vcoords((glamor_pixmap_private *)NULL, temp_xscale, temp_yscale, 0, 0, w, h, @@ -750,7 +750,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale); - glamor_set_normalize_tcoords(source_xscale, + glamor_set_normalize_tcoords(source_priv, source_xscale, source_yscale, x, y, x + w, y + h, @@ -763,7 +763,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glActiveTexture(GL_TEXTURE0); - dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->fbo->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -988,16 +988,16 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) data = malloc(stride * pixmap->drawable.height); } else { dispatch = glamor_get_dispatch(glamor_priv); - if (pixmap_priv->fbo->pbo == 0) + if (pixmap_priv->base.fbo->pbo == 0) dispatch->glGenBuffers(1, - &pixmap_priv->fbo->pbo); + &pixmap_priv->base.fbo->pbo); glamor_put_dispatch(glamor_priv); - pbo = pixmap_priv->fbo->pbo; + pbo = pixmap_priv->base.fbo->pbo; } if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) { stride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth); - pixmap_priv->drm_stride = pixmap->devKind; + pixmap_priv->base.drm_stride = pixmap->devKind; pixmap->devKind = stride; } @@ -1014,9 +1014,9 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } if (pbo != 0) - pixmap_priv->fbo->pbo_valid = 1; + pixmap_priv->base.fbo->pbo_valid = 1; - pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; + pixmap_priv->base.gl_fbo = GLAMOR_FBO_DOWNLOADED; pixmap->devPrivate.ptr = dst; @@ -1036,14 +1036,14 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) GCPtr gc = NULL; int ret = FALSE; - drawable = &pixmap_priv->container->drawable; + drawable = &pixmap_priv->base.pixmap->drawable; - if (pixmap_priv->container->drawable.width == pixmap_priv->fbo->width - && pixmap_priv->container->drawable.height == pixmap_priv->fbo->height) + if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width + && pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height) return TRUE; - old_fbo = pixmap_priv->fbo; - glamor_priv = pixmap_priv->glamor_priv; + old_fbo = pixmap_priv->base.fbo; + glamor_priv = pixmap_priv->base.glamor_priv; if (!old_fbo) return FALSE; @@ -1058,7 +1058,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) scratch_priv = glamor_get_pixmap_private(scratch); - if (!scratch_priv || !scratch_priv->fbo) + if (!scratch_priv || !scratch_priv->base.fbo) goto fail; ValidateGC(&scratch->drawable, gc); @@ -1069,7 +1069,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) 0, 0); old_fbo = glamor_pixmap_detach_fbo(pixmap_priv); new_fbo = glamor_pixmap_detach_fbo(scratch_priv); - glamor_pixmap_attach_fbo(pixmap_priv->container, new_fbo); + glamor_pixmap_attach_fbo(pixmap_priv->base.pixmap, new_fbo); glamor_pixmap_attach_fbo(scratch, old_fbo); DEBUGF("old %dx%d type %d\n", @@ -1139,11 +1139,11 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces return NULL; sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); - pbo = sub_pixmap_priv ? (sub_pixmap_priv->fbo ? sub_pixmap_priv->fbo->pbo : 0): 0; + pbo = sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.fbo->pbo : 0): 0; - if (pixmap_priv->is_picture) { - sub_pixmap_priv->pict_format = pixmap_priv->pict_format; - sub_pixmap_priv->is_picture = pixmap_priv->is_picture; + if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) { + sub_pixmap_priv->base.picture = pixmap_priv->base.picture; + sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; } if (pbo) @@ -1157,7 +1157,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces if (pbo) { assert(sub_pixmap->devPrivate.ptr == NULL); sub_pixmap->devPrivate.ptr = data; - sub_pixmap_priv->fbo->pbo_valid = 1; + sub_pixmap_priv->base.fbo->pbo_valid = 1; } #if 0 struct pixman_box16 box; @@ -1189,10 +1189,10 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int if (access != GLAMOR_ACCESS_RO) { sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); if (sub_pixmap_priv - && sub_pixmap_priv->fbo - && sub_pixmap_priv->fbo->pbo_valid) { + && sub_pixmap_priv->base.fbo + && sub_pixmap_priv->base.fbo->pbo_valid) { bits = NULL; - pbo = sub_pixmap_priv->fbo->pbo; + pbo = sub_pixmap_priv->base.fbo->pbo; } else { bits = sub_pixmap->devPrivate.ptr; pbo = 0; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index a817f78a5..2172d177e 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -309,19 +309,132 @@ typedef struct glamor_pixmap_fbo { * @gl_tex: The pixmap is in a gl texture originally. * @is_picture: The drawable is attached to a picture. * @pict_format: the corresponding picture's format. - * @container: The corresponding pixmap's pointer. + * @pixmap: The corresponding pixmap's pointer. + * + * For GLAMOR_TEXTURE_LARGE, nbox should larger than 1. + * And the box and fbo will both have nbox elements. + * and box[i] store the relatively coords in this pixmap + * of the fbo[i]. The reason why use boxes not region to + * represent this structure is we may need to use overlapped + * boxes for one pixmap for some special reason. + * + * pixmap + * ****************** + * * fbo0 * fbo1 * + * * * * + * ****************** + * * fbo2 * fbo3 * + * * * * + * ****************** + * + * Let's assume the texture has size of 1024x1024 + * box[0] = {0,0,1024,1024} + * box[1] = {1024,0,2048,2048} + * ... + * + * For GLAMOR_TEXTURE_ATLAS nbox should be 1. And box + * and fbo both has one elements, and the box store + * the relatively coords in the fbo of this pixmap: + * + * fbo + * ****************** + * * pixmap * + * * ********* * + * * * * * + * * ********* * + * * * + * ****************** + * + * Assume the pixmap is at the (100,100) relatively to + * the fbo's origin. + * box[0]={100, 100, 1124, 1124}; + * + * Considering large pixmap is not a normal case, to keep + * it simple, I designe it as the following way. + * When deal with a large pixmap, it split the working + * rectangle into serval boxes, and each box fit into a + * corresponding fbo. And then the rendering function will + * loop from the left-top box to the right-bottom box, + * each time, we will set current box and current fbo + * to the box and fbo elements. Thus the inner routines + * can handle it as normal, only the coords calculation need + * to aware of it's large pixmap. + * + * Currently, we haven't implemented the atlas pixmap. + * **/ -typedef struct glamor_pixmap_private { + +typedef struct glamor_pixmap_clipped_regions{ + int block_idx; + RegionPtr region; +} glamor_pixmap_clipped_regions; + +#define SET_PIXMAP_FBO_CURRENT(priv, idx) \ + do { \ + if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + (priv)->large.base.fbo = priv->large.fbo_array[idx]; \ + (priv)->large.box = priv->large.box_array[idx]; \ + } \ + } while(0) + +typedef struct glamor_pixmap_private_base { + glamor_pixmap_type_t type; unsigned char gl_fbo:2; unsigned char is_picture:1; unsigned char gl_tex:1; - glamor_pixmap_type_t type; glamor_pixmap_fbo *fbo; - PictFormatShort pict_format; - PixmapPtr container; + PixmapPtr pixmap; int drm_stride; glamor_screen_private *glamor_priv; -} glamor_pixmap_private; + PicturePtr picture; +}glamor_pixmap_private_base_t; + +/* + * @base.fbo: current fbo. + * @box: current fbo's coords in the whole pixmap. + * @block_w: block width of this large pixmap. + * @block_h: block height of this large pixmap. + * @block_wcnt: block count in one block row. + * @block_hcnt: block count in one block column. + * @nbox: total block count. + * @box_array: contains each block's corresponding box. + * @fbo_array: contains each block's fbo pointer. + * + **/ +typedef struct glamor_pixmap_private_large { + union { + glamor_pixmap_type_t type; + glamor_pixmap_private_base_t base; + }; + BoxRec box; + int block_w; + int block_h; + int block_wcnt; + int block_hcnt; + int nbox; + BoxPtr box_array; + glamor_pixmap_fbo **fbo_array; +}glamor_pixmap_private_large_t; + +/* + * @box: the relative coords in the corresponding fbo. + */ +typedef struct glamor_pixmap_private_atlas { + union { + glamor_pixmap_type_t type; + glamor_pixmap_private_base_t base; + }; + BoxRec box; +}glamor_pixmap_private_atlas_t; + +typedef struct glamor_pixmap_private { + union { + glamor_pixmap_type_t type; + glamor_pixmap_private_base_t base; + glamor_pixmap_private_large_t large; + glamor_pixmap_private_atlas_t atlas; + }; +}glamor_pixmap_private; /* * Pixmap dynamic status, used by dynamic upload feature. @@ -404,6 +517,7 @@ glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_pri glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag); void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); +void glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv); void glamor_purge_fbo(glamor_pixmap_fbo *fbo); void glamor_init_pixmap_fbo(ScreenPtr screen); @@ -413,6 +527,11 @@ void glamor_fbo_expire(glamor_screen_private *glamor_priv); void glamor_init_pixmap_fbo(ScreenPtr screen); void glamor_fini_pixmap_fbo(ScreenPtr screen); +glamor_pixmap_fbo * +glamor_create_fbo_array(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag, + int block_w, int block_h, glamor_pixmap_private *); + Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); /* glamor_copyarea.c */ @@ -543,6 +662,19 @@ void glamor_init_putimage_shaders(ScreenPtr screen); void glamor_fini_putimage_shaders(ScreenPtr screen); /* glamor_render.c */ +Bool +glamor_composite_clipped_region(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + RegionPtr region, + int x_source, + int y_source, + int x_mask, + int y_mask, + int x_dest, + int y_dest); + void glamor_composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, @@ -552,6 +684,7 @@ void glamor_composite(CARD8 op, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + void glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, @@ -654,7 +787,6 @@ Bool glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h, int stride, void *bits, int pbo); - PixmapPtr glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access); @@ -662,6 +794,44 @@ void glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access); +glamor_pixmap_clipped_regions * +glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *clipped_nbox, int repeat_type); + +glamor_pixmap_clipped_regions * +glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, + RegionPtr region, + int *n_region, + int inner_block_w, int inner_block_h); + +glamor_pixmap_clipped_regions * +glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, + RegionPtr region, int *n_region, int dx, int dy, int repeat_type); + +Bool +glamor_composite_largepixmap_region(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private * source_pixmap_priv, + glamor_pixmap_private * mask_pixmap_priv, + glamor_pixmap_private * dest_pixmap_priv, + RegionPtr region, Bool force_clip, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height); + +Bool +glamor_get_transform_block_size(struct pixman_transform *transform, + int block_w, int block_h, + int *transformed_block_w, + int *transformed_block_h); + +void +glamor_get_transform_extent_from_box(struct pixman_box32 *temp_box, + struct pixman_transform *transform); /** * Upload a picture to gl texture. Similar to the @@ -757,5 +927,6 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER #endif +#define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index d1e3a83a1..6d62bd7bc 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -295,9 +295,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); - if (pixmap_priv->is_picture) { - temp_pixmap_priv->pict_format = pixmap_priv->pict_format; - temp_pixmap_priv->is_picture = pixmap_priv->is_picture; + if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) { + temp_pixmap_priv->base.picture = pixmap_priv->base.picture; + temp_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; } glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 907d65b8e..6a584ba6e 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -545,7 +545,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, dispatch = glamor_get_dispatch(glamor_priv); dispatch->glActiveTexture(GL_TEXTURE0 + unit); - dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); + dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex); repeat_type = picture->repeatType; switch (picture->repeatType) { case RepeatNone: @@ -1047,7 +1047,7 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("source == dest\n"); goto fail; } - if (!source_pixmap_priv || source_pixmap_priv->gl_fbo == 0) { + if (!source_pixmap_priv || source_pixmap_priv->base.gl_fbo == 0) { /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex * equal to zero when the pixmap is screen pixmap. Then we may * refer the tex zero directly latter in the composition. @@ -1068,7 +1068,7 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("mask == dest\n"); goto fail; } - if (!mask_pixmap_priv || mask_pixmap_priv->gl_fbo == 0) { + if (!mask_pixmap_priv || mask_pixmap_priv->base.gl_fbo == 0) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD mask_status = GLAMOR_UPLOAD_PENDING; #else @@ -1259,7 +1259,7 @@ glamor_composite_with_shader(CARD8 op, width = rects->width; height = rects->height; - glamor_set_normalize_vcoords(dst_xscale, + glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale, dst_yscale, x_dest, y_dest, x_dest + width, y_dest + height, @@ -1269,14 +1269,14 @@ glamor_composite_with_shader(CARD8 op, if (key.source != SHADER_SOURCE_SOLID) { if (source->transform) glamor_set_transformed_normalize_tcoords - (src_matrix, src_xscale, + (source_pixmap_priv, src_matrix, src_xscale, src_yscale, x_source, y_source, x_source + width, y_source + height, glamor_priv->yInverted, source_texcoords); else glamor_set_normalize_tcoords - (src_xscale, src_yscale, + (source_pixmap_priv, src_xscale, src_yscale, x_source, y_source, x_source + width, y_source + height, glamor_priv->yInverted, @@ -1287,7 +1287,7 @@ glamor_composite_with_shader(CARD8 op, && key.mask != SHADER_MASK_SOLID) { if (mask->transform) glamor_set_transformed_normalize_tcoords - (mask_matrix, + (mask_pixmap_priv, mask_matrix, mask_xscale, mask_yscale, x_mask, y_mask, x_mask + width, y_mask + height, @@ -1295,7 +1295,7 @@ glamor_composite_with_shader(CARD8 op, mask_texcoords); else glamor_set_normalize_tcoords - (mask_xscale, + (mask_pixmap_priv, mask_xscale, mask_yscale, x_mask, y_mask, x_mask + width, y_mask + height, glamor_priv->yInverted, diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 6790550a3..c6b88d267 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -166,13 +166,12 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, &src_yscale); dispatch->glUseProgram(glamor_priv->tile_prog); - wh[0] = (float)src_pixmap_priv->fbo->width / tile->drawable.width; - wh[1] = (float)src_pixmap_priv->fbo->height / tile->drawable.height; + glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv); dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, - src_pixmap_priv->fbo->tex); + src_pixmap_priv->base.fbo->tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -186,7 +185,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - glamor_set_normalize_tcoords(src_xscale, src_yscale, + glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, + src_yscale, tile_x1, tile_y1, tile_x2, tile_y2, glamor_priv->yInverted, @@ -197,7 +197,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, source_texcoords); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glamor_set_normalize_vcoords(dst_xscale, dst_yscale, + glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, + dst_yscale, x1, y1, x2, y2, glamor_priv->yInverted, vertices); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 4af6739dd..90a1657e6 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -41,26 +41,50 @@ #define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height; \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height; \ } while(0) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height; \ + *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.fbo->width; \ + *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height; \ } while(0) -#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv) \ - (priv->fbo->width != priv->container->drawable.width \ - || priv->fbo->height != priv->container->drawable.height) +#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv) \ + (priv->base.fbo->width != priv->base.pixmap->drawable.width \ + || priv->base.fbo->height != priv->base.pixmap->drawable.height) \ -#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv) do { \ - wh[0] = (float)priv->fbo->width \ - / priv->container->drawable.width; \ - wh[1] = (float)priv->fbo->height \ - / priv->container->drawable.height; \ - } while(0) +#define PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, w, h) \ + do { \ + if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + w = priv->large.box.x2 - priv->large.box.x1; \ + h = priv->large.box.y2 - priv->large.box.y1; \ + } else { \ + w = priv->base.pixmap->drawable.width; \ + h = priv->base.pixmap->drawable.height; \ + } \ + } while(0) + +#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv) \ + do { \ + int actual_w, actual_h; \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, actual_w, actual_h); \ + wh[0] = (float)priv->base.fbo->width / actual_w; \ + wh[1] = (float)priv->base.fbo->height / actual_h; \ + } while(0) + +#define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \ + do { \ + if (_priv_ && (_priv_)->type \ + == GLAMOR_TEXTURE_LARGE) { \ + *(_xoff_) = - (_priv_)->large.box.x1; \ + *(_yoff_) = - (_priv_)->large.box.y1; \ + } else { \ + *(_xoff_) = 0; \ + *(_yoff_) = 0; \ + } \ + } while(0) #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_) \ + ((float)xFixedFrac(_val_) / 65536.0)) @@ -82,67 +106,113 @@ } \ } while(0) -#define glamor_set_transformed_point(matrix, xscale, yscale, texcoord, \ - x, y, yInverted) \ +#define glamor_transform_point(matrix, tx, ty, x, y) \ do { \ - float result[4]; \ int i; \ - float tx, ty; \ - \ + float result[4]; \ for (i = 0; i < 3; i++) { \ result[i] = (matrix)[i * 3] * (x) + (matrix)[i * 3 + 1] * (y) \ + (matrix)[i * 3 + 2]; \ } \ tx = result[0] / result[2]; \ ty = result[1] / result[2]; \ + } while(0) + +#define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_, \ + texcoord, yInverted) \ + do { \ + (texcoord)[0] = t_from_x_coord_x(xscale, _tx_); \ + if (yInverted) \ + (texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);\ + else \ + (texcoord)[1] = t_from_x_coord_y(yscale, _ty_); \ + DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0], \ + (texcoord)[1]); \ + } while(0) + +#define glamor_set_transformed_point(priv, matrix, xscale, \ + yscale, texcoord, \ + x, y, \ + yInverted) \ + do { \ + float tx, ty; \ + int fbo_x_off, fbo_y_off; \ + pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ + glamor_transform_point(matrix, tx, ty, x, y); \ + DEBUGF("tx %f ty %f fbooff %d %d \n", \ + tx, ty, fbo_x_off, fbo_y_off); \ \ + tx += fbo_x_off; \ + ty += fbo_y_off; \ (texcoord)[0] = t_from_x_coord_x(xscale, tx); \ if (yInverted) \ (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \ else \ (texcoord)[1] = t_from_x_coord_y(yscale, ty); \ + DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \ } while(0) - -#define glamor_set_transformed_normalize_tcoords( matrix, \ +#define glamor_set_transformed_normalize_tcoords( priv, \ + matrix, \ xscale, \ yscale, \ tx1, ty1, tx2, ty2, \ yInverted, texcoords) \ do { \ - glamor_set_transformed_point(matrix, xscale, yscale, \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ texcoords, tx1, ty1, \ yInverted); \ - glamor_set_transformed_point(matrix, xscale, yscale, \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ texcoords + 2, tx2, ty1, \ yInverted); \ - glamor_set_transformed_point(matrix, xscale, yscale, \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ texcoords + 4, tx2, ty2, \ yInverted); \ - glamor_set_transformed_point(matrix, xscale, yscale, \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ texcoords + 6, tx1, ty2, \ yInverted); \ } while (0) -#define glamor_set_normalize_tcoords(xscale, yscale, x1, y1, x2, y2, \ - yInverted, vertices) \ +#define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \ + ty1, tx2, ty2, \ + yInverted, vertices) \ do { \ - (vertices)[0] = t_from_x_coord_x(xscale, x1); \ - (vertices)[2] = t_from_x_coord_x(xscale, x2); \ + (vertices)[0] = t_from_x_coord_x(xscale, tx1); \ + (vertices)[2] = t_from_x_coord_x(xscale, tx2); \ (vertices)[4] = (vertices)[2]; \ (vertices)[6] = (vertices)[0]; \ if (yInverted) { \ - (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \ - (vertices)[5] = t_from_x_coord_y_inverted(yscale, y2); \ + (vertices)[1] = t_from_x_coord_y_inverted(yscale, ty1); \ + (vertices)[5] = t_from_x_coord_y_inverted(yscale, ty2); \ } \ else { \ - (vertices)[1] = t_from_x_coord_y(yscale, y1); \ - (vertices)[5] = t_from_x_coord_y(yscale, y2); \ + (vertices)[1] = t_from_x_coord_y(yscale, ty1); \ + (vertices)[5] = t_from_x_coord_y(yscale, ty2); \ } \ (vertices)[3] = (vertices)[1]; \ (vertices)[7] = (vertices)[5]; \ + DEBUGF("texture %f %f %f %f\n", tx1, ty1, tx2, ty2); \ + DEBUGF("texture %f %f %f %f\n", (vertices)[0], (vertices)[1], \ + (vertices)[2], (vertices)[3]); \ + DEBUGF("texture %f %f %f %f\n", (vertices)[4], (vertices)[5], \ + (vertices)[6], (vertices)[7]); \ } while(0) +#define glamor_set_normalize_tcoords(priv, xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + float tx1, tx2, ty1, ty2; \ + int fbo_x_off, fbo_y_off; \ + pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ + tx1 = x1 + fbo_x_off; \ + tx2 = x2 + fbo_x_off; \ + ty1 = y1 + fbo_y_off; \ + ty2 = y2 + fbo_y_off; \ + _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ + tx2, ty2, yInverted, vertices); \ + } while(0) + #define glamor_set_tcoords(width, height, x1, y1, x2, y2, \ yInverted, vertices) \ do { \ @@ -163,24 +233,27 @@ } while(0) -#define glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2, \ +#define glamor_set_normalize_vcoords(priv, xscale, yscale, \ + x1, y1, x2, y2, \ yInverted, vertices) \ - do { \ - (vertices)[0] = v_from_x_coord_x(xscale, x1); \ - (vertices)[2] = v_from_x_coord_x(xscale, x2); \ - (vertices)[4] = (vertices)[2]; \ - (vertices)[6] = (vertices)[0]; \ - if (yInverted) { \ - (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ - (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2); \ - } \ - else { \ - (vertices)[1] = v_from_x_coord_y(yscale, y1); \ - (vertices)[5] = v_from_x_coord_y(yscale, y2); \ - } \ - (vertices)[3] = (vertices)[1]; \ - (vertices)[7] = (vertices)[5]; \ - } while(0) + do { \ + int fbo_x_off, fbo_y_off; \ + pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ + (vertices)[0] = v_from_x_coord_x(xscale, x1 + fbo_x_off); \ + (vertices)[2] = v_from_x_coord_x(xscale, x2 + fbo_x_off); \ + (vertices)[4] = (vertices)[2]; \ + (vertices)[6] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1 + fbo_y_off);\ + (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2 + fbo_y_off);\ + } \ + else { \ + (vertices)[1] = v_from_x_coord_y(yscale, y1 + fbo_y_off); \ + (vertices)[5] = v_from_x_coord_y(yscale, y2 + fbo_y_off); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[7] = (vertices)[5]; \ + } while(0) #define glamor_set_normalize_pt(xscale, yscale, x, y, \ yInverted, pt) \ @@ -244,10 +317,11 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) #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)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define glamor_check_fbo_size(_glamor_,_w_, _h_) ((_w_) > 0 && (_h_) > 0 \ - && (_w_) < _glamor_->max_fbo_size \ - && (_h_) < _glamor_->max_fbo_size) + && (_w_) <= _glamor_->max_fbo_size \ + && (_h_) <= _glamor_->max_fbo_size) /* For 1bpp pixmap, we don't store it as texture. */ #define glamor_check_pixmap_fbo_depth(_depth_) ( \ @@ -258,9 +332,9 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) || _depth_ == 30 \ || _depth_ == 32) -#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1) -#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) -#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED)) +#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->base.is_picture == 1) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->base.gl_fbo == GLAMOR_FBO_NORMAL) +#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv) (pixmap_priv && (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED)) /** * Borrow from uxa. @@ -315,7 +389,7 @@ format_for_pixmap(PixmapPtr pixmap) pixmap_priv = glamor_get_pixmap_private(pixmap); if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) - pict_format = pixmap_priv->pict_format; + pict_format = pixmap_priv->base.picture->format; else pict_format = format_for_depth(pixmap->drawable.depth); @@ -659,7 +733,7 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, pixmap_priv = glamor_get_pixmap_private(pixmap); if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) - pict_format = pixmap_priv->pict_format; + pict_format = pixmap_priv->base.picture->format; else pict_format = format_for_depth(pixmap->drawable.depth); @@ -783,6 +857,24 @@ inline static Bool glamor_ddx_fallback_check_gc(GCPtr gc) } return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable)); } +inline static Bool glamor_is_large_pixmap(PixmapPtr pixmap) +{ + glamor_pixmap_private *priv; + + priv = glamor_get_pixmap_private(pixmap); + return (priv->type == GLAMOR_TEXTURE_LARGE); +} + +inline static Bool glamor_is_large_picture(PicturePtr picture) +{ + PixmapPtr pixmap; + + if (picture->pDrawable) { + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + return glamor_is_large_pixmap(pixmap); + } + return FALSE; +} inline static Bool glamor_tex_format_is_readable(GLenum format) { From e96ea02010874a3a46f212f42134083bd29fefe3 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 01:52:14 +0800 Subject: [PATCH 381/462] largepixmap: Implement infrastructure for large pixmap. Added infrastructure for largepixmap, this commit implemented: 1. Create/Destroy large pixmap. 2. Upload/Download large pixmap. 3. Implement basic repeat normal support. 3. tile/fill/copyarea large pixmap get supported. The most complicated part glamor_composite still not implemented. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor.c | 40 ++- glamor/glamor_copyarea.c | 329 ++++++++++++++++----- glamor/glamor_fbo.c | 121 +++++++- glamor/glamor_fill.c | 102 +++++-- glamor/glamor_largepixmap.c | 412 ++++++++++++++++++++++++++ glamor/glamor_pixmap.c | 330 +++++++++++++++++---- glamor/glamor_priv.h | 5 +- glamor/glamor_render.c | 560 ++++++++++++++++++++++-------------- glamor/glamor_tile.c | 192 ++++++++++--- glamor/glamor_utils.h | 72 ++++- 11 files changed, 1711 insertions(+), 453 deletions(-) create mode 100644 glamor/glamor_largepixmap.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 2e94ffd73..421846c62 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -42,6 +42,7 @@ libglamor_la_SOURCES = \ glamor_glyphblt.c\ glamor_polyops.c\ glamor_pixmap.c\ + glamor_largepixmap.c\ glamor_picture.c\ glamor_window.c\ glamor_gl_dispatch.c\ diff --git a/glamor/glamor.c b/glamor/glamor.c index a22f445d4..74b22d39b 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -141,9 +141,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; - if (usage == GLAMOR_CREATE_PIXMAP_CPU - || (w == 0 && h == 0) - || !glamor_check_pixmap_fbo_depth(depth)) + if ((usage == GLAMOR_CREATE_PIXMAP_CPU + || (w == 0 && h == 0) + || !glamor_check_pixmap_fbo_depth(depth)) + || (!GLAMOR_TEXTURED_LARGE_PIXMAP && + !glamor_check_fbo_size(glamor_priv, w, h))) return fbCreatePixmap(screen, w, h, depth, usage); else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); @@ -161,10 +163,24 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->base.pixmap = pixmap; pixmap_priv->base.glamor_priv = glamor_priv; - pixmap_priv->type = type; gl_iformat_for_depth(depth, &format); - fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); + + pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); + + if (type == GLAMOR_MEMORY_MAP || glamor_check_fbo_size(glamor_priv, w, h)) { + pixmap_priv->type = type; + fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); + } + else { + DEBUGF("Create LARGE pixmap %p width %d height %d\n", pixmap, w, h); + pixmap_priv->type = GLAMOR_TEXTURE_LARGE; + fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage, + glamor_priv->max_fbo_size, + glamor_priv->max_fbo_size, + pixmap_priv); + } if (fbo == NULL) { fbDestroyPixmap(pixmap); @@ -174,8 +190,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_pixmap_attach_fbo(pixmap, fbo); - pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); return pixmap; } @@ -186,13 +200,8 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap) glamor_pixmap_private *pixmap_priv; pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv != NULL) { - glamor_pixmap_fbo *fbo; - fbo = glamor_pixmap_detach_fbo(pixmap_priv); - if (fbo) - glamor_destroy_fbo(fbo); - free(pixmap_priv); - } + if (pixmap_priv != NULL) + glamor_pixmap_destroy_fbo(pixmap_priv); } } @@ -315,6 +324,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_gl_has_extension("GL_EXT_framebuffer_blit"); glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); +#ifdef MAX_FBO_SIZE + glamor_priv->max_fbo_size = MAX_FBO_SIZE; +#endif glamor_set_debug_level(&glamor_debug_level); diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 84a449c8c..4d68dbe66 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -40,11 +40,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, ScreenPtr screen = dst->pScreen; PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - glamor_pixmap_private *src_pixmap_priv; + glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; int dst_x_off, dst_y_off, src_x_off, src_y_off, i; + int fbo_x_off, fbo_y_off; + int src_fbo_x_off, src_fbo_y_off; if (!glamor_priv->has_fbo_blit) { glamor_delayed_fallback(screen, @@ -52,17 +54,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, return FALSE; } src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); if (gc) { if (gc->alu != GXcopy) { glamor_delayed_fallback(screen, "non-copy ALU\n"); return FALSE; } - if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_delayed_fallback(screen, - "non-solid planemask\n"); - return FALSE; - } } if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { @@ -73,6 +71,9 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, if (glamor_set_destination_pixmap(dst_pixmap)) return FALSE; + pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off); + pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->base.fbo->fb); @@ -80,7 +81,10 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, &dst_y_off); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - src_y_off += dy; + dst_x_off += fbo_x_off; + dst_y_off += fbo_y_off; + src_y_off += dy + src_fbo_y_off; + src_x_off += src_fbo_x_off; for (i = 0; i < nbox; i++) { if (glamor_priv->yInverted) { @@ -154,17 +158,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src, int src_x_off, src_y_off, dst_x_off, dst_y_off; enum glamor_pixmap_status src_status = GLAMOR_NONE; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; - int alu = GXcopy; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n"); - return FALSE; - } - - if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) { + if (!src_pixmap_priv->base.gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); return FALSE; @@ -177,11 +175,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, #endif } - if (gc) { - if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - return FALSE; - alu = gc->alu; - } pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); @@ -191,10 +184,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, alu)) { - glamor_put_dispatch(glamor_priv); - return FALSE; - } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -239,8 +228,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, for (i = 0; i < nbox; i++) { - glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, - dst_yscale, + glamor_set_normalize_vcoords(dst_pixmap_priv, + dst_xscale, dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, box[i].x2 + dst_x_off, @@ -248,7 +237,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, + glamor_set_normalize_tcoords(src_pixmap_priv, + src_xscale, src_yscale, box[i].x1 + dx, box[i].y1 + dy, @@ -270,19 +260,18 @@ glamor_copy_n_to_n_textured(DrawablePtr src, return TRUE; } -static Bool -_glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, - void *closure, Bool fallback) +static Bool +__glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure) { - glamor_access_t dst_access; PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; DrawablePtr temp_src = src; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; @@ -296,32 +285,20 @@ _glamor_copy_n_to_n(DrawablePtr src, int overlaped = 0; Bool ret = FALSE; - if (nbox == 0) - return TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; glamor_priv = glamor_get_screen_private(dst->pScreen); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest pixmap %p has no fbo. \n", - dst_pixmap); - goto fail; - } - - if (!src_pixmap_priv) { - glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - } - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - if (src_pixmap_priv->base.fbo && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { + if (src_pixmap_priv->base.fbo + && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { int x_shift = abs(src_x_off - dx - dst_x_off); int y_shift = abs(src_y_off - dy - dst_y_off); for (i = 0; i < nbox; i++) { @@ -332,6 +309,11 @@ _glamor_copy_n_to_n(DrawablePtr src, } } } + DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", + box[0].x1, box[0].y1, + box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, + dx, dy, + src_pixmap, dst_pixmap); #ifndef GLAMOR_GLES2 if ((overlaped || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) @@ -345,10 +327,13 @@ _glamor_copy_n_to_n(DrawablePtr src, /* Overlaped indicate the src and dst are the same pixmap. */ if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) - && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) + && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1) * 4 > src_pixmap->drawable.width * - src_pixmap->drawable.height))) { + src_pixmap->drawable.height) + || !(glamor_check_fbo_size(glamor_priv, + src_pixmap->drawable.width, + src_pixmap->drawable.height))))) { temp_pixmap = glamor_create_pixmap(screen, bound.x2 - bound.x1, @@ -357,9 +342,11 @@ _glamor_copy_n_to_n(DrawablePtr src, drawable.depth, overlaped ? 0 : GLAMOR_CREATE_PIXMAP_CPU); + assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size); + assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size); if (!temp_pixmap) - goto fail; - glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + goto done; + glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1); temp_src = &temp_pixmap->drawable; if (overlaped) @@ -371,7 +358,7 @@ _glamor_copy_n_to_n(DrawablePtr src, fbCopyNtoN(src, temp_src, gc, box, nbox, temp_dx + bound.x1, temp_dy + bound.y1, reverse, upsidedown, bitplane, closure); - glamor_transform_boxes(box, nbox, bound.x1, bound.y1); + glamor_translate_boxes(box, nbox, bound.x1, bound.y1); temp_dx = -bound.x1; temp_dy = -bound.y1; } else { @@ -383,13 +370,221 @@ _glamor_copy_n_to_n(DrawablePtr src, if (glamor_copy_n_to_n_textured (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { ret = TRUE; - goto done; + } +done: + if (temp_src != src) + glamor_destroy_pixmap(temp_pixmap); + return ret; +} + +static Bool +_glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure, Bool fallback) +{ + glamor_access_t dst_access; + PixmapPtr dst_pixmap, src_pixmap; + glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + BoxPtr extent; + RegionRec region; + ScreenPtr screen; + int src_x_off, src_y_off, dst_x_off, dst_y_off; + Bool ret = FALSE; + int ok = TRUE; + int force_clip = 0; + + if (nbox == 0) + return TRUE; + dst_pixmap = glamor_get_drawable_pixmap(dst); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + src_pixmap = glamor_get_drawable_pixmap(src); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + screen = dst_pixmap->drawable.pScreen; + + glamor_priv = glamor_get_screen_private(dst->pScreen); + + DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", + box[0].x1, box[0].y1, + box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, + dx, dy, + src_pixmap, dst_pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) + goto fall_back; + + if (gc) { + if (!glamor_set_planemask(dst_pixmap, gc->planemask)) + goto fail; + dispatch = glamor_get_dispatch(glamor_priv); + if (!glamor_set_alu(dispatch, gc->alu)) { + glamor_put_dispatch(glamor_priv); + goto fail; + } + glamor_put_dispatch(glamor_priv); } + if (!src_pixmap_priv) { + glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + } - fail: - - if (!fallback + glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, + &src_y_off); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, + &dst_y_off); + + RegionInitBoxes(®ion, box, nbox); + extent = RegionExtents(®ion); + + if (!glamor_check_fbo_size(glamor_priv, + extent->x2 - extent->x1, extent->y2 - extent->y1) + && (src_pixmap_priv->type == GLAMOR_MEMORY + || (src_pixmap_priv == dst_pixmap_priv))) { + force_clip = 1; + } + + if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + glamor_pixmap_clipped_regions *clipped_dst_regions; + int n_dst_region, i, j; + PixmapPtr temp_source_pixmap; + glamor_pixmap_private *temp_source_priv = NULL; + int temp_dx = 0, temp_dy = 0; + + RegionTranslate(®ion, dst_x_off, dst_y_off); + if (!force_clip) + clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, + ®ion, &n_dst_region, 0); + else + clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, + ®ion, &n_dst_region, + glamor_priv->max_fbo_size, + glamor_priv->max_fbo_size); + for(i = 0; i < n_dst_region; i++) + { + int n_src_region; + glamor_pixmap_clipped_regions *clipped_src_regions; + BoxPtr current_boxes; + int n_current_boxes; + + SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, clipped_dst_regions[i].block_idx); + + temp_source_pixmap = NULL; + if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionTranslate(clipped_dst_regions[i].region, + -dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy); + clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, + clipped_dst_regions[i].region, + &n_src_region, 0); + DEBUGF("Source is large pixmap.\n"); + for (j = 0; j < n_src_region; j++) + { + if (src_pixmap_priv != dst_pixmap_priv) + SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx); + else if (src_pixmap_priv == dst_pixmap_priv && + clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx) { + /* source and the dest are the same, but need different block_idx. + * we create a empty pixmap and fill the required source fbo and box to + * it. It's a little hacky, but avoid extra copy. */ + temp_source_pixmap = glamor_create_pixmap(src->pScreen, 0, 0, + src->depth, 0); + if (!temp_source_pixmap) + goto fail; + src->pScreen->ModifyPixmapHeader(temp_source_pixmap, + src_pixmap->drawable.width, + src_pixmap->drawable.height, + 0, 0, src_pixmap->devKind, NULL); + temp_source_priv = glamor_get_pixmap_private(temp_source_pixmap); + *temp_source_priv = *src_pixmap_priv; + temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; + temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx]; + /* XXX need revisit here. */ + temp_dx = dx/* - src_x_off*/; + temp_dy = dy/* - src_y_off*/; + } + assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv + && (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); + + RegionTranslate(clipped_src_regions[j].region, + -src_x_off - dx, + -src_y_off - dy); + current_boxes = RegionRects(clipped_src_regions[j].region); + n_current_boxes = RegionNumRects(clipped_src_regions[j].region); + DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n", + clipped_dst_regions[i].block_idx, + clipped_src_regions[j].block_idx); + DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", + current_boxes[0].x1, current_boxes[0].y1, + current_boxes[0].x2, current_boxes[0].y2, + dx, dy, src_pixmap, dst_pixmap); + if (!temp_source_pixmap) + ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, + n_current_boxes, dx, dy, reverse, + upsidedown, bitplane, closure); + else { + ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, + n_current_boxes, temp_dx, temp_dy, reverse, + upsidedown, bitplane, closure); + temp_source_priv->type = GLAMOR_MEMORY; + temp_source_priv->base.fbo = NULL; + glamor_destroy_pixmap(temp_source_pixmap); + temp_source_pixmap = NULL; + } + + RegionDestroy(clipped_src_regions[j].region); + if (!ok) { + assert(0); + goto fail; + } + } + free(clipped_src_regions); + } else { + RegionTranslate(clipped_dst_regions[i].region, + - dst_x_off, + - dst_y_off); + current_boxes = RegionRects(clipped_dst_regions[i].region); + n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); + + DEBUGF("dest pixmap fbo idx %d \n", + clipped_dst_regions[i].block_idx); + DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", + current_boxes[0].x1, current_boxes[0].y1, + current_boxes[0].x2, current_boxes[0].y2, + dx, dy, src_pixmap, dst_pixmap); + + ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, + n_current_boxes, dx, dy, reverse, + upsidedown, bitplane, closure); + + } + RegionDestroy(clipped_dst_regions[i].region); + } + free(clipped_dst_regions); + RegionUninit(®ion); + } else { + ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, + closure); + } + +fail: + dispatch = glamor_get_dispatch(glamor_priv); + glamor_set_alu(dispatch, GXcopy); + glamor_put_dispatch(glamor_priv); + + if (ok) + return TRUE; +fall_back: + if (!fallback && glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst)) goto done; @@ -428,8 +623,6 @@ _glamor_copy_n_to_n(DrawablePtr src, done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); - if (temp_src != src) - glamor_destroy_pixmap(temp_pixmap); return ret; } @@ -455,10 +648,10 @@ glamor_copy_n_to_n(DrawablePtr src, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, + Bool upsidedown, Pixel bitplane, void *closure) { - _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, + _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure, TRUE); } @@ -471,10 +664,10 @@ glamor_copy_n_to_n_nf(DrawablePtr src, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, + Bool upsidedown, Pixel bitplane, void *closure) { - return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, + return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure, FALSE); } diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 5337149cd..1ab76868d 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -175,7 +175,8 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) if (fbo->fb == 0 || n_format == -1 || fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) { - fbo->glamor_priv->tick ++; + fbo->glamor_priv->tick += GLAMOR_CACHE_EXPIRE_MAX; + glamor_fbo_expire(fbo->glamor_priv); glamor_purge_fbo(fbo); return; } @@ -404,6 +405,92 @@ no_tex: return fbo; } +static glamor_pixmap_fbo * +_glamor_create_fbo_array(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag, + int block_w, int block_h, + glamor_pixmap_private *pixmap_priv, + int has_fbo) +{ + int block_wcnt; + int block_hcnt; + glamor_pixmap_fbo **fbo_array; + BoxPtr box_array; + int i,j; + glamor_pixmap_private_large_t *priv; + + priv = &pixmap_priv->large; + + block_wcnt = (w + block_w - 1) / block_w; + block_hcnt = (h + block_h - 1) / block_h; + + box_array = calloc(block_wcnt * block_hcnt, sizeof(box_array[0])); + if (box_array == NULL) + return NULL; + + fbo_array = calloc(block_wcnt * block_hcnt, sizeof(glamor_pixmap_fbo*)); + if (fbo_array == NULL) { + free(box_array); + return FALSE; + } + for(i = 0; i < block_hcnt; i++) + { + int block_y1, block_y2; + int fbo_w, fbo_h; + + block_y1 = i * block_h; + block_y2 = (block_y1 + block_h) > h ? h : (block_y1 + block_h); + fbo_h = block_y2 - block_y1; + + for (j = 0; j < block_wcnt; j++) + { + box_array[i * block_wcnt + j].x1 = j * block_w; + box_array[i * block_wcnt + j].y1 = block_y1; + box_array[i * block_wcnt + j].x2 = (j + 1) * block_w > w ? w : (j + 1) * block_w; + box_array[i * block_wcnt + j].y2 = block_y2; + fbo_w = box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt + j].x1; + if (!has_fbo) + fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv, + fbo_w, fbo_h, format, + GLAMOR_CREATE_PIXMAP_FIXUP); + else + fbo_array[i * block_wcnt + j] = priv->base.fbo; + if (fbo_array[i * block_wcnt + j] == NULL) + goto cleanup; + } + } + + priv->box = box_array[0]; + priv->box_array = box_array; + priv->fbo_array = fbo_array; + priv->block_wcnt = block_wcnt; + priv->block_hcnt = block_hcnt; + return fbo_array[0]; + +cleanup: + for(i = 0; i < block_wcnt * block_hcnt; i++) + if ((fbo_array)[i]) + glamor_destroy_fbo((fbo_array)[i]); + free(box_array); + free(fbo_array); + return NULL; +} + + +/* Create a fbo array to cover the w*h region, by using block_w*block_h + * block.*/ +glamor_pixmap_fbo * +glamor_create_fbo_array(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag, + int block_w, int block_h, + glamor_pixmap_private *pixmap_priv) +{ + pixmap_priv->large.block_w = block_w; + pixmap_priv->large.block_h = block_h; + return _glamor_create_fbo_array(glamor_priv, w, h, format, flag, + block_w, block_h, pixmap_priv, 0); +} + glamor_pixmap_fbo * glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) { @@ -428,23 +515,13 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL) { - glamor_screen_private *glamor_priv; - glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - pixmap_priv = calloc(1, sizeof(*pixmap_priv)); - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, pixmap_priv); - pixmap_priv->base.pixmap = pixmap; - pixmap_priv->base.glamor_priv = glamor_priv; - pixmap_priv->type = GLAMOR_MEMORY; - } - if (pixmap_priv->base.fbo) return; pixmap_priv->base.fbo = fbo; switch (pixmap_priv->type) { + case GLAMOR_TEXTURE_LARGE: case GLAMOR_TEXTURE_ONLY: case GLAMOR_TEXTURE_DRM: pixmap_priv->base.gl_fbo = 1; @@ -462,6 +539,23 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) } } +void +glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv) +{ + glamor_pixmap_fbo *fbo; + if (priv->type == GLAMOR_TEXTURE_LARGE) { + int i; + glamor_pixmap_private_large_t *large = &priv->large; + for(i = 0; i < large->block_wcnt * large->block_hcnt; i++) + glamor_destroy_fbo(large->fbo_array[i]); + free(large->fbo_array); + } else { + fbo = glamor_pixmap_detach_fbo(priv); + if (fbo) + glamor_destroy_fbo(fbo); + free(priv); + } +} Bool glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) @@ -472,7 +566,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { + if (pixmap_priv->base.fbo == NULL) { fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, @@ -492,7 +586,6 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_pixmap_ensure_fb(pixmap_priv->base.fbo); } - pixmap_priv = glamor_get_pixmap_private(pixmap); return TRUE; } diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index b63756db8..5b84dd66e 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -180,10 +180,9 @@ glamor_fini_solid_shader(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } -Bool -glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, - unsigned long fg_pixel) +static void +_glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + float *color) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = @@ -195,14 +194,49 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, int x2 = x + width; int y1 = y; int y2 = y + height; - GLfloat color[4]; float vertices[8]; GLfloat xscale, yscale; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("dest %p has no fbo.\n", pixmap); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glUseProgram(glamor_priv->solid_prog); + + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, color); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); + + glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, + x1, y1, + x2, y2, + glamor_priv->yInverted, vertices); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); +} + +Bool +glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv; + glamor_gl_dispatch *dispatch; + GLfloat color[4]; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return FALSE; - } if (!glamor_set_planemask(pixmap, planemask)) { glamor_fallback @@ -216,8 +250,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, &color[2], &color[3], format_for_pixmap(pixmap)); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, alu)) { if (alu == GXclear) @@ -228,23 +260,47 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, return FALSE; } } - dispatch->glUseProgram(glamor_priv->solid_prog); - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, - 1, color); + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + int i,j; - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + RegionInitBoxes(®ion, &box, 1); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + for(i = 0; i < n_region; i++) + { + BoxPtr boxes; + int nbox; + SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); + + boxes = RegionRects(clipped_regions[i].region); + nbox = RegionNumRects(clipped_regions[i].region); + for(j = 0; j < nbox; j++) + { + _glamor_solid(pixmap, boxes[j].x1, boxes[j].y1, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, color); + } + RegionDestroy(clipped_regions[i].region); + } + free(clipped_regions); + RegionUninit(®ion); + } else + _glamor_solid(pixmap, + x, + y, + width, height, + color); - glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, x1, y1, x2, y2, - glamor_priv->yInverted, vertices); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); + return TRUE; } diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c new file mode 100644 index 000000000..e8c103056 --- /dev/null +++ b/glamor/glamor_largepixmap.c @@ -0,0 +1,412 @@ +#include + +#include "glamor_priv.h" + +/** + * Clip the boxes regards to each pixmap's block array. + * + * Should translate the region to relative coords to the pixmap, + * start at (0,0). + */ +#if 0 +//#define DEBUGF(str, ...) do {} while(0) +#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) +//#define DEBUGRegionPrint(x) do {} while (0) +#define DEBUGRegionPrint RegionPrint +#endif + +static glamor_pixmap_clipped_regions * +__glamor_compute_clipped_regions(int block_w, + int block_h, + int block_stride, + int x, int y, + int w, int h, + RegionPtr region, + int *n_region, + int repeat) +{ + glamor_pixmap_clipped_regions * clipped_regions; + BoxPtr extent; + int start_x, start_y, end_x, end_y; + int start_block_x, start_block_y; + int end_block_x, end_block_y; + int i, j; + int width, height; + RegionRec temp_region; + RegionPtr current_region; + int block_idx; + int k = 0; + int temp_block_idx; + + extent = RegionExtents(region); + start_x = MAX(x, extent->x1); + start_y = MAX(y, extent->y1); + end_x = MIN(x + w, extent->x2); + end_y = MIN(y + h, extent->y2); + + DEBUGF("start compute clipped regions:\n"); + DEBUGF("block w %d h %d x %d y %d w %d h %d, block_stride %d \n", + block_w, block_h, x, y, w, h, block_stride); + DEBUGRegionPrint(region); + + DEBUGF("start_x %d start_y %d end_x %d end_y %d \n", start_x, start_y, end_x, end_y); + + if (start_x >= end_x || start_y >= end_y) { + *n_region = 0; + return NULL; + } + + width = end_x - start_x; + height = end_y - start_y; + start_block_x = (start_x - x)/ block_w; + start_block_y = (start_y - y)/ block_h; + end_block_x = (end_x - x)/ block_w; + end_block_y = (end_y - y)/ block_h; + + clipped_regions = calloc((end_block_x - start_block_x + 1) + * (end_block_y - start_block_y + 1), + sizeof(*clipped_regions)); + + block_idx = (start_block_y - 1) * block_stride; + + DEBUGF("startx %d starty %d endx %d endy %d \n", + start_x, start_y, end_x, end_y); + DEBUGF("start_block_x %d end_block_x %d \n", start_block_x, end_block_x); + DEBUGF("start_block_y %d end_block_y %d \n", start_block_y, end_block_y); + + for(j = start_block_y; j <= end_block_y; j++) + { + block_idx += block_stride; + temp_block_idx = block_idx + start_block_x; + for(i = start_block_x; + i <= end_block_x; i++, temp_block_idx++) + { + BoxRec temp_box; + temp_box.x1 = x + i * block_w; + temp_box.y1 = y + j * block_h; + temp_box.x2 = MIN(temp_box.x1 + block_w, end_x); + temp_box.y2 = MIN(temp_box.y1 + block_h, end_y); + RegionInitBoxes(&temp_region, &temp_box, 1); + DEBUGF("block idx %d \n",temp_block_idx); + DEBUGRegionPrint(&temp_region); + current_region = RegionCreate(NULL, 4); + RegionIntersect(current_region, &temp_region, region); + DEBUGF("i %d j %d region: \n",i ,j); + DEBUGRegionPrint(current_region); + if (RegionNumRects(current_region)) { + clipped_regions[k].region = current_region; + clipped_regions[k].block_idx = temp_block_idx; + k++; + } else + RegionDestroy(current_region); + RegionUninit(&temp_region); + } + } + + *n_region = k; + return clipped_regions; +} + +/** + * Do a two round clipping, + * first is to clip the region regard to current pixmap's + * block array. Then for each clipped region, do a inner + * block clipping. This is to make sure the final result + * will be shapped by inner_block_w and inner_block_h, and + * the final region also will not cross the pixmap's block + * boundary. + * + * This is mainly used by transformation support when do + * compositing. + */ + +glamor_pixmap_clipped_regions * +glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, + RegionPtr region, + int *n_region, + int inner_block_w, int inner_block_h) +{ + glamor_pixmap_clipped_regions * clipped_regions, *inner_regions, *result_regions; + int i, j, x, y, k, inner_n_regions; + int width, height; + glamor_pixmap_private_large_t *priv; + priv = &pixmap_priv->large; + + DEBUGF("ext called \n"); + + if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + clipped_regions = calloc(1, sizeof(*clipped_regions)); + if (clipped_regions == NULL) { + *n_region = 0; + return NULL; + } + clipped_regions[0].region = RegionCreate(NULL, 1); + clipped_regions[0].block_idx = 0; + RegionCopy(clipped_regions[0].region, region); + *n_region = 1; + priv->block_w = priv->base.pixmap->drawable.width; + priv->block_h = priv->base.pixmap->drawable.height; + priv->box_array = &priv->box; + priv->box.x1 = priv->box.y1 = 0; + priv->box.x2 = priv->block_w; + priv->box.y2 = priv->block_h; + } else { + clipped_regions = __glamor_compute_clipped_regions(priv->block_w, + priv->block_h, + priv->block_wcnt, + 0, 0, + priv->base.pixmap->drawable.width, + priv->base.pixmap->drawable.height, + region, n_region, 0 + ); + + if (clipped_regions == NULL) { + *n_region = 0; + return NULL; + } + } + if (inner_block_w >= priv->block_w + && inner_block_h >= priv->block_h) + return clipped_regions; + result_regions = calloc(*n_region + * ((priv->block_w + inner_block_w - 1)/inner_block_w) + * ((priv->block_h + inner_block_h - 1)/ inner_block_h), + sizeof(*result_regions)); + k = 0; + for(i = 0; i < *n_region; i++) + { + x = priv->box_array[clipped_regions[i].block_idx].x1; + y = priv->box_array[clipped_regions[i].block_idx].y1; + width = priv->box_array[clipped_regions[i].block_idx].x2 - x; + height = priv->box_array[clipped_regions[i].block_idx].y2 - y; + inner_regions = __glamor_compute_clipped_regions(inner_block_w, + inner_block_h, + 0, x, y, + width, + height, + clipped_regions[i].region, + &inner_n_regions, 0); + for(j = 0; j < inner_n_regions; j++) + { + result_regions[k].region = inner_regions[j].region; + result_regions[k].block_idx = clipped_regions[i].block_idx; + k++; + } + free(inner_regions); + } + *n_region = k; + free(clipped_regions); + return result_regions; +} + +/** + * Clip the boxes regards to each pixmap's block array. + * + * Should translate the region to relative coords to the pixmap, + * start at (0,0). + * + * @is_transform: if it is set, it has a transform matrix. + * + * XXX Not support repeatPad currently. + */ + +static glamor_pixmap_clipped_regions * +_glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, + RegionPtr region, int *n_region, + int repeat_type, int is_transform) +{ + glamor_pixmap_clipped_regions * clipped_regions; + BoxPtr extent; + int i, j; + int width, height; + RegionPtr current_region; + int pixmap_width, pixmap_height; + int m; + BoxRec repeat_box; + RegionRec repeat_region; + int right_shift = 0; + int down_shift = 0; + int x_center_shift = 0, y_center_shift = 0; + glamor_pixmap_private_large_t *priv; + priv = &pixmap_priv->large; + + DEBUGRegionPrint(region); + if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { + clipped_regions = calloc(1, sizeof(*clipped_regions)); + clipped_regions[0].region = RegionCreate(NULL, 1); + clipped_regions[0].block_idx = 0; + RegionCopy(clipped_regions[0].region, region); + *n_region = 1; + return clipped_regions; + } + + pixmap_width = priv->base.pixmap->drawable.width; + pixmap_height = priv->base.pixmap->drawable.height; + if (repeat_type == 0) { + clipped_regions = __glamor_compute_clipped_regions(priv->block_w, + priv->block_h, + priv->block_wcnt, + 0, 0, + priv->base.pixmap->drawable.width, + priv->base.pixmap->drawable.height, + region, n_region, 0 + ); + return clipped_regions; + } else if (repeat_type != RepeatNormal) { + *n_region = 0; + return NULL; + } + extent = RegionExtents(region); + + x_center_shift = extent->x1 / pixmap_width; + if (x_center_shift < 0) + x_center_shift--; + if (abs(x_center_shift) & 1) + x_center_shift++; + y_center_shift = extent->y1 / pixmap_height; + if (y_center_shift < 0) + y_center_shift--; + if (abs(y_center_shift) & 1) + y_center_shift++; + + if (extent->x1 < 0) + right_shift = ((-extent->x1 + pixmap_width - 1) / pixmap_width ); + if (extent->y1 < 0) + down_shift = ((-extent->y1 + pixmap_height - 1) / pixmap_height ); + + if (right_shift != 0 || down_shift != 0) { + if (repeat_type == RepeatReflect) { + right_shift = (right_shift + 1)&~1; + down_shift = (down_shift + 1)&~1; + } + RegionTranslate(region, right_shift * pixmap_width, down_shift * pixmap_height); + } + + extent = RegionExtents(region); + width = extent->x2 - extent->x1; + height = extent->y2 - extent->y1; + /* Tile a large pixmap to another large pixmap. + * We can't use the target large pixmap as the + * loop variable, instead we need to loop for all + * the blocks in the tile pixmap. + * + * simulate repeat each single block to cover the + * target's blocks. Two special case: + * a block_wcnt == 1 or block_hcnt ==1, then we + * only need to loop one direction as the other + * direction is fully included in the first block. + * + * For the other cases, just need to start + * from a proper shiftx/shifty, and then increase + * y by tile_height each time to walk trhough the + * target block and then walk trhough the target + * at x direction by increate tile_width each time. + * + * This way, we can consolidate all the sub blocks + * of the target boxes into one tile source's block. + * + * */ + m = 0; + clipped_regions = calloc(priv->block_wcnt * priv->block_hcnt, + sizeof(*clipped_regions)); + if (clipped_regions == NULL) { + *n_region = 0; + return NULL; + } + if (right_shift != 0 || down_shift != 0) { + DEBUGF("region to be repeated shifted \n"); + DEBUGRegionPrint(region); + } + DEBUGF("repeat pixmap width %d height %d \n", pixmap_width, pixmap_height); + DEBUGF("extent x1 %d y1 %d x2 %d y2 %d \n", extent->x1, extent->y1, extent->x2, extent->y2); + for(j = 0; j < priv->block_hcnt; j++) + { + for(i = 0; i < priv->block_wcnt; i++) + { + int dx = pixmap_width; + int dy = pixmap_height; + int idx; + int shift_x; + int shift_y; + int saved_y1, saved_y2; + int x_idx = 0, y_idx = 0; + RegionRec temp_region; + + shift_x = (extent->x1 / pixmap_width) * pixmap_width; + shift_y = (extent->y1 / pixmap_height) * pixmap_height; + idx = j * priv->block_wcnt + i; + if (repeat_type == RepeatReflect) { + x_idx = (extent->x1 / pixmap_width); + y_idx = (extent->y1 / pixmap_height); + } + + /* Construct a rect to clip the target region. */ + repeat_box.x1 = shift_x + priv->box_array[idx].x1; + repeat_box.y1 = shift_y + priv->box_array[idx].y1; + if (priv->block_wcnt == 1) + repeat_box.x2 = extent->x2; + else + repeat_box.x2 = shift_x + priv->box_array[idx].x2; + if (priv->block_hcnt == 1) + repeat_box.y2 = extent->y2; + else + repeat_box.y2 = shift_y + priv->box_array[idx].y2; + + current_region = RegionCreate(NULL, 4); + RegionInit(&temp_region, NULL, 4); + DEBUGF("init repeat box %d %d %d %d \n", + repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2); + + if (repeat_type == RepeatNormal) { + saved_y1 = repeat_box.y1; + saved_y2 = repeat_box.y2; + for(; repeat_box.x1 < extent->x2; + repeat_box.x1 += dx, repeat_box.x2 += dx) + { + repeat_box.y1 = saved_y1; + repeat_box.y2 = saved_y2; + for( repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2; + repeat_box.y1 < extent->y2; + repeat_box.y1 += dy, repeat_box.y2 += dy) + { + + RegionInitBoxes(&repeat_region, &repeat_box, 1); + DEBUGF("Start to clip repeat region: \n"); + DEBUGRegionPrint(&repeat_region); + RegionIntersect(&temp_region, &repeat_region, region); + DEBUGF("clip result:\n"); + DEBUGRegionPrint(&temp_region); + RegionAppend(current_region, &temp_region); + RegionUninit(&repeat_region); + } + } + } + DEBUGF("dx %d dy %d \n", dx, dy); + + if (RegionNumRects(current_region)) { + + if ((right_shift != 0 || down_shift != 0)) + RegionTranslate(current_region, + -right_shift * pixmap_width, + -down_shift * pixmap_height); + clipped_regions[m].region = current_region; + clipped_regions[m].block_idx = idx; + m++; + } else + RegionDestroy(current_region); + RegionUninit(&temp_region); + } + } + + if (right_shift != 0 || down_shift != 0) + RegionTranslate(region, -right_shift * pixmap_width, -down_shift * pixmap_height); + *n_region = m; + + return clipped_regions; +} + +glamor_pixmap_clipped_regions * +glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *n_region, int repeat_type) +{ + return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0); +} diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index fa05bed8b..ca38a2bc3 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -83,9 +83,11 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo, int x0, int y0, int w void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { + int w,h; + + PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap_priv, w, h); glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0, - pixmap_priv->base.pixmap->drawable.width, - pixmap_priv->base.pixmap->drawable.height); + w, h); } int @@ -489,16 +491,23 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty } ready_to_upload: + /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ if (no_alpha == 0 && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip) { + int fbo_x_off, fbo_y_off; assert(pixmap_priv->base.fbo->tex); + pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); + + assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0); + assert(x + fbo_x_off + w <= pixmap_priv->base.fbo->width); + assert(y + fbo_y_off + h <= pixmap_priv->base.fbo->height); __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex, format, type, - x, y, w, h, + x + fbo_x_off, y + fbo_y_off, w, h, bits, pbo); return TRUE; } @@ -515,7 +524,6 @@ ready_to_upload: x + w, y + h, glamor_priv->yInverted, vertices); - /* Slow path, we need to flip y or wire alpha to 1. */ dispatch = glamor_get_dispatch(glamor_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -586,6 +594,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + if (pixmap_priv->base.gl_fbo) + return 0; + if (pixmap_priv->base.fbo && (pixmap_priv->base.fbo->width < pixmap->drawable.width || pixmap_priv->base.fbo->height < pixmap->drawable.height)) { @@ -605,8 +616,10 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int flag = GLAMOR_CREATE_FBO_NO_FBO; } - if ((flag == 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) - || (flag != 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) + if ((flag == GLAMOR_CREATE_FBO_NO_FBO + && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) + || (flag == 0 + && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) return 0; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) @@ -614,35 +627,63 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int else iformat = format; - if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { - - fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, - iformat, - flag); - if (fbo == NULL) { - glamor_fallback - ("upload failed, depth %d x %d @depth %d \n", - pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth); - return -1; - } - - glamor_pixmap_attach_fbo(pixmap, fbo); - } else { - /* We do have a fbo, but it may lack of fb or tex. */ - glamor_pixmap_ensure_fbo(pixmap, iformat, flag); - } + if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag)) + return -1; return 0; } +/* + * upload sub region to a large region. + * */ +static void +glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits, + int src_stride, int bpp, + int x, int y, int w, int h) +{ + int j; + int byte_per_pixel; + + byte_per_pixel = bpp / 8; + src_bits += y * src_stride + (x * byte_per_pixel); + + for(j = y; j < y + h; j++) + { + memcpy(dst_bits, src_bits, w * byte_per_pixel); + src_bits += src_stride; + dst_bits += dst_stride; + } +} +/* + * download sub region from a large region. + */ +static void +glamor_get_bits(char *dst_bits, int dst_stride, char *src_bits, + int src_stride, int bpp, + int x, int y, int w, int h) +{ + int j; + int byte_per_pixel; + + byte_per_pixel = bpp / 8; + dst_bits += y * dst_stride + x * byte_per_pixel; + + for(j = y; j < y + h; j++) + { + memcpy(dst_bits, src_bits, w * byte_per_pixel); + src_bits += src_stride; + dst_bits += dst_stride; + } +} + + Bool glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h, int stride, void *bits, int pbo) { GLenum format, type; int no_alpha, revert, swap_rb; + glamor_pixmap_private *pixmap_priv; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, @@ -657,7 +698,77 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) return FALSE; - return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb, + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + void *sub_bits; + int i,j; + + sub_bits = malloc(h * stride); + if (sub_bits == NULL) + return FALSE; + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + RegionInitBoxes(®ion, &box, 1); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); + for(i = 0; i < n_region; i++) + { + BoxPtr boxes; + int nbox; + int temp_stride; + void *temp_bits; + + assert(pbo == 0); + + SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); + + boxes = RegionRects(clipped_regions[i].region); + nbox = RegionNumRects(clipped_regions[i].region); + DEBUGF("split to %d boxes\n", nbox); + for(j = 0; j < nbox; j++) + { + temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1, + pixmap->drawable.depth); + + if (boxes[j].x1 == x && temp_stride == stride) { + temp_bits = (char*)bits + (boxes[j].y1 - y) * stride; + } else { + temp_bits = sub_bits; + glamor_put_bits(temp_bits, temp_stride, bits, stride, + pixmap->drawable.bitsPerPixel, + boxes[j].x1 - x, boxes[j].y1 - y, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1); + } + DEBUGF("upload x %d y %d w %d h %d temp stride %d \n", + boxes[j].x1 - x, boxes[j].y1 - y, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, temp_stride); + if (_glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, + revert, swap_rb, boxes[j].x1, boxes[j].y1, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, + temp_stride, temp_bits, pbo) == FALSE) { + RegionUninit(®ion); + free(sub_bits); + assert(0); + return FALSE; + } + } + RegionDestroy(clipped_regions[i].region); + } + free(sub_bits); + free(clipped_regions); + RegionUninit(®ion); + return TRUE; + } else + return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb, x, y, w, h, stride, bits, pbo); } @@ -671,8 +782,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv - && (pixmap_priv->base.fbo) + if ((pixmap_priv->base.fbo) && (pixmap_priv->base.fbo->pbo_valid)) { data = NULL; pbo = pixmap_priv->base.fbo->pbo; @@ -737,7 +847,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe temp_xscale = 1.0 / w; temp_yscale = 1.0 / h; - glamor_set_normalize_vcoords((glamor_pixmap_private *)NULL, temp_xscale, + glamor_set_normalize_vcoords((struct glamor_pixmap_private*)NULL,temp_xscale, temp_yscale, 0, 0, w, h, @@ -793,13 +903,15 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe * The pixmap must have a valid FBO, otherwise return a NULL. * */ -void * -glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, - int stride, void *bits, int pbo, glamor_access_t access) +static void * +_glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format, + GLenum type, int no_alpha, + int revert, int swap_rb, + int x, int y, int w, int h, + int stride, void *bits, int pbo, glamor_access_t access) { glamor_pixmap_private *pixmap_priv; - GLenum format, type, gl_access = 0, gl_usage = 0; - int no_alpha, revert, swap_rb; + GLenum gl_access = 0, gl_usage = 0; void *data, *read; ScreenPtr screen; glamor_screen_private *glamor_priv = @@ -808,6 +920,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, glamor_pixmap_fbo *temp_fbo = NULL; int need_post_conversion = 0; int need_free_data = 0; + int fbo_x_off, fbo_y_off; data = bits; screen = pixmap->drawable.pScreen; @@ -831,18 +944,6 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, assert(0); } - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &revert, - &swap_rb, 0)) { - ErrorF("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - assert(0); // Should never happen. - return NULL; - } - glamor_set_destination_pixmap_priv_nc(pixmap_priv); need_post_conversion = (revert > REVERT_NORMAL); @@ -857,6 +958,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, } } + pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 && !need_post_conversion && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { @@ -868,6 +971,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, } x = 0; y = 0; + fbo_x_off = 0; + fbo_y_off = 0; } dispatch = glamor_get_dispatch(glamor_priv); @@ -890,7 +995,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, NULL, gl_usage); } - dispatch->glReadPixels(x, y, w, h, format, type, data); + dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data); if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); @@ -913,7 +1018,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, stride * h, NULL, GL_STREAM_READ); - dispatch->glReadPixels(0, 0, w, h, + dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, 0); read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); @@ -946,6 +1051,107 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, return bits; } +void * +glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, + int stride, void *bits, int pbo, glamor_access_t access) +{ + GLenum format, type; + int no_alpha, revert, swap_rb; + glamor_pixmap_private *pixmap_priv; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &no_alpha, + &revert, + &swap_rb, 1)) { + glamor_fallback("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + return NULL; + } + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return NULL; + + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + void *sub_bits; + int i,j; + + sub_bits = malloc(h * stride); + if (sub_bits == NULL) + return FALSE; + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + RegionInitBoxes(®ion, &box, 1); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h); + for(i = 0; i < n_region; i++) + { + BoxPtr boxes; + int nbox; + int temp_stride; + void *temp_bits; + + assert(pbo == 0); + SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); + + boxes = RegionRects(clipped_regions[i].region); + nbox = RegionNumRects(clipped_regions[i].region); + for(j = 0; j < nbox; j++) + { + temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1, + pixmap->drawable.depth); + + if (boxes[j].x1 == x && temp_stride == stride) { + temp_bits = (char*)bits + (boxes[j].y1 - y) * stride; + } else { + temp_bits = sub_bits; + } + DEBUGF("download x %d y %d w %d h %d temp stride %d \n", + boxes[j].x1, boxes[j].y1, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, temp_stride); + + /* For large pixmap, we don't support pbo currently.*/ + assert(pbo == 0); + if (_glamor_download_sub_pixmap_to_cpu(pixmap, format, type, no_alpha, + revert, swap_rb, boxes[j].x1, boxes[j].y1, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1, + temp_stride, temp_bits, pbo, access) == FALSE) { + RegionUninit(®ion); + free(sub_bits); + assert(0); + return NULL; + } + if (boxes[j].x1 != x || temp_stride != stride) + glamor_get_bits(bits, stride, temp_bits, temp_stride, + pixmap->drawable.bitsPerPixel, + boxes[j].x1 - x , boxes[j].y1 - y, + boxes[j].x2 - boxes[j].x1, + boxes[j].y2 - boxes[j].y1); + } + + RegionDestroy(clipped_regions[i].region); + } + free(sub_bits); + free(clipped_regions); + RegionUninit(®ion); + return bits; + } else + return _glamor_download_sub_pixmap_to_cpu(pixmap, format, type, no_alpha, revert, swap_rb, + x, y, w, h, stride, + bits, pbo, access); +} + /** * Move a pixmap to CPU memory. @@ -984,7 +1190,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (access == GLAMOR_ACCESS_WO || glamor_priv->gl_flavor == GLAMOR_GL_ES2 - || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)) { + || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted) + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { data = malloc(stride * pixmap->drawable.height); } else { dispatch = glamor_get_dispatch(glamor_priv); @@ -1024,6 +1231,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } /* fixup a fbo to the exact size as the pixmap. */ +/* XXX LARGE pixmap? */ Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) { @@ -1038,8 +1246,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) drawable = &pixmap_priv->base.pixmap->drawable; - if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width - && pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height) + if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)) return TRUE; old_fbo = pixmap_priv->base.fbo; @@ -1058,7 +1265,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) scratch_priv = glamor_get_pixmap_private(scratch); - if (!scratch_priv || !scratch_priv->base.fbo) + if (!scratch_priv->base.fbo) goto fail; ValidateGC(&scratch->drawable, gc); @@ -1111,14 +1318,13 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces void *data; int pbo; int flag; - - assert(x >= 0 && y >= 0); + if (x < 0 || y < 0) + return NULL; w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w; h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h; if (access == GLAMOR_ACCESS_WO) { sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); - ErrorF("WO\n"); return sub_pixmap; } @@ -1127,7 +1333,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return NULL; - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) flag = GLAMOR_CREATE_PIXMAP_CPU; else flag = GLAMOR_CREATE_PIXMAP_MAP; @@ -1141,17 +1347,16 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); pbo = sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.fbo->pbo : 0): 0; - if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) { + if (pixmap_priv->base.is_picture) { sub_pixmap_priv->base.picture = pixmap_priv->base.picture; sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; } if (pbo) data = NULL; - else { + else data = sub_pixmap->devPrivate.ptr; - assert(flag != GLAMOR_CREATE_PIXMAP_MAP); - } + data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind, data, pbo, access); if (pbo) { @@ -1173,7 +1378,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); - glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap, NULL, &box, 1, dx, dy, 0, 0, 0, NULL); + glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box, 1, dx, dy, 0, 0, 0, NULL); glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1); #endif @@ -1188,8 +1393,7 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int glamor_pixmap_private *sub_pixmap_priv; if (access != GLAMOR_ACCESS_RO) { sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); - if (sub_pixmap_priv - && sub_pixmap_priv->base.fbo + if (sub_pixmap_priv->base.fbo && sub_pixmap_priv->base.fbo->pbo_valid) { bits = NULL; pbo = sub_pixmap_priv->base.fbo->pbo; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 2172d177e..d9f643837 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -927,6 +927,9 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER #endif -#define GLAMOR_TEXTURED_LARGE_PIXMAP 1 +#define GLAMOR_TEXTURED_LARGE_PIXMAP 0 +#if 0 +#define MAX_FBO_SIZE 512 /* For test purpose only. */ +#endif #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6a584ba6e..48a5bb3ee 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -37,7 +37,12 @@ #ifdef RENDER #include "mipict.h" #include "fbpict.h" - +#if 0 +//#define DEBUGF(str, ...) do {} while(0) +#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) +//#define DEBUGRegionPrint(x) do {} while (0) +#define DEBUGRegionPrint RegionPrint +#endif struct shader_key { enum shader_source source; enum shader_mask mask; @@ -606,18 +611,20 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #endif /* XXX may be we can eaxctly check whether we need to touch * the out-of-box area then determine whether we need to fix. - * */ - if (repeat_type != RepeatNone) - repeat_type += RepeatFix; - else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - if (picture->transform - || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + **/ + /*if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE)*/ { + if (repeat_type != RepeatNone) repeat_type += RepeatFix; - } - - if (repeat_type >= RepeatFix) { - glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); - dispatch->glUniform2fv(wh_location, 1, wh); + else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (picture->transform + || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + repeat_type += RepeatFix; + } + if (repeat_type >= RepeatFix) { + glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); + dispatch->glUniform2fv(wh_location, 1, wh); + } } dispatch->glUniform1i(repeat_location, repeat_type); glamor_put_dispatch(glamor_priv); @@ -687,53 +694,44 @@ glamor_composite_with_copy(CARD8 op, INT16 x_source, INT16 y_source, INT16 x_dest, - INT16 y_dest, CARD16 width, CARD16 height) + INT16 y_dest, + RegionPtr region) { - RegionRec region; int ret = FALSE; - if (!source->pDrawable) return FALSE; if (!compatible_formats(op, dest, source)) return FALSE; - if (source->repeat || source->transform) + 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; - if (!miComputeCompositeRegion(®ion, - source, NULL, dest, - x_source, y_source, - 0, 0, x_dest, y_dest, width, height)) - return TRUE; - if (PICT_FORMAT_A(source->format) == 0) { /* Fallback if we sample outside the source so that we * swizzle the correct clear color for out-of-bounds texels. */ - if (region.extents.x1 + x_source - x_dest < 0) + if (region->extents.x1 + x_source - x_dest < 0) goto cleanup_region; - if (region.extents.x2 + x_source - x_dest > source->pDrawable->width) + if (region->extents.x2 + x_source - x_dest > source->pDrawable->width) goto cleanup_region; - if (region.extents.y1 + y_source - y_dest < 0) + if (region->extents.y1 + y_source - y_dest < 0) goto cleanup_region; - if (region.extents.y2 + y_source - y_dest > source->pDrawable->height) + if (region->extents.y2 + y_source - y_dest > source->pDrawable->height) goto cleanup_region; } - ret = glamor_copy_n_to_n_nf(source->pDrawable, dest->pDrawable, NULL, - REGION_RECTS(®ion), - REGION_NUM_RECTS(®ion), + RegionRects(region), RegionNumRects(region), x_source - x_dest, y_source - y_dest, FALSE, FALSE, 0, NULL); cleanup_region: - REGION_UNINIT(dest->pDrawable->pScreen, ®ion); return ret; } @@ -929,12 +927,44 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src, return FALSE; } +static void +glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, + int repeat_type, + float *matrix, + float xscale, float yscale, + int x1, int y1, int x2, int y2, + int yInverted, float *texcoords) +{ + if (!matrix && repeat_type == RepeatNone) + glamor_set_normalize_tcoords(priv, xscale, yscale, + x1, y1, + x2, y2, + yInverted, + texcoords); + else if (matrix && repeat_type == RepeatNone) + glamor_set_transformed_normalize_tcoords(priv, matrix, xscale, + yscale, x1, y1, + x2, y2, + yInverted, + texcoords); + else if (!matrix && repeat_type != RepeatNone) + glamor_set_repeat_normalize_tcoords(priv, repeat_type, + xscale, yscale, + x1, y1, + x2, y2, + yInverted, + texcoords); + else if (matrix && repeat_type != RepeatNone) + assert(0); +} + static Bool glamor_composite_with_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - int nrect, glamor_composite_rect_t * rects) + int nrect, + glamor_composite_rect_t * rects) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_screen_private *glamor_priv = @@ -959,6 +989,7 @@ glamor_composite_with_shader(CARD8 op, enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; + float *psrc_matrix = NULL, *pmask_matrix = NULL; GLfloat source_solid_color[4], mask_solid_color[4]; int vert_stride = 4; int nrect_max; @@ -970,20 +1001,23 @@ glamor_composite_with_shader(CARD8 op, goto fail; } memset(&key, 0, sizeof(key)); - if (!source->pDrawable) { - if (source->pSourcePict->type == SourcePictTypeSolidFill) { - key.source = SHADER_SOURCE_SOLID; - glamor_get_rgba_from_pixel(source-> - pSourcePict->solidFill. - color, - &source_solid_color[0], - &source_solid_color[1], - &source_solid_color[2], - &source_solid_color[3], - PICT_a8r8g8b8); - } else { - glamor_fallback("gradient source\n"); - goto fail; + if (!source) { + key.source = SHADER_SOURCE_SOLID; + source_solid_color[0] = 0.0; + source_solid_color[1] = 0.0; + source_solid_color[2] = 0.0; + source_solid_color[3] = 0.0; + } else if (!source->pDrawable) { + if (source->pSourcePict->type == SourcePictTypeSolidFill) { + key.source = SHADER_SOURCE_SOLID; + glamor_get_rgba_from_pixel(source-> + pSourcePict->solidFill. + color, + &source_solid_color[0], + &source_solid_color[1], + &source_solid_color[2], + &source_solid_color[3], + PICT_a8r8g8b8); } } else { key.source = SHADER_SOURCE_TEXTURE_ALPHA; @@ -999,9 +1033,6 @@ glamor_composite_with_shader(CARD8 op, &mask_solid_color[1], &mask_solid_color[2], &mask_solid_color[3], PICT_a8r8g8b8); - } else { - glamor_fallback("gradient mask\n"); - goto fail; } } else { key.mask = SHADER_MASK_TEXTURE_ALPHA; @@ -1029,7 +1060,7 @@ glamor_composite_with_shader(CARD8 op, key.in = SHADER_IN_SOURCE_ONLY; } - if (source->alphaMap) { + if (source && source->alphaMap) { glamor_fallback("source alphaMap\n"); goto fail; } @@ -1044,13 +1075,14 @@ glamor_composite_with_shader(CARD8 op, source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); if (source_pixmap == dest_pixmap) { + /* XXX source and the dest share the same texture. + * Does it need special handle? */ glamor_fallback("source == dest\n"); - goto fail; } - if (!source_pixmap_priv || source_pixmap_priv->base.gl_fbo == 0) { - /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex + if (source_pixmap_priv->base.gl_fbo == 0) { + /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex * equal to zero when the pixmap is screen pixmap. Then we may - * refer the tex zero directly latter in the composition. + * refer the tex zero directly latter in the composition. * It seems that it works fine, but it may have potential problem*/ #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD source_status = GLAMOR_UPLOAD_PENDING; @@ -1068,7 +1100,7 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("mask == dest\n"); goto fail; } - if (!mask_pixmap_priv || mask_pixmap_priv->base.gl_fbo == 0) { + if (mask_pixmap_priv->base.gl_fbo == 0) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD mask_status = GLAMOR_UPLOAD_PENDING; #else @@ -1095,20 +1127,20 @@ glamor_composite_with_shader(CARD8 op, } if (source->format != saved_source_format) { - glamor_picture_format_fixup(source, - source_pixmap_priv); + //glamor_picture_format_fixup(source, + // source_pixmap_priv); } - /* XXX + /* 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 + * 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 + * 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 + * 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. @@ -1156,13 +1188,15 @@ glamor_composite_with_shader(CARD8 op, * transformed source and mask, if the transform is not int translate. */ if (key.source != SHADER_SOURCE_SOLID && source->transform - && !pixman_transform_is_int_translate(source->transform)) { + && !pixman_transform_is_int_translate(source->transform) + && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) goto fail; } if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID && mask->transform - && !pixman_transform_is_int_translate(mask->transform)) { + && !pixman_transform_is_int_translate(mask->transform) + && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) goto fail; } @@ -1217,7 +1251,10 @@ glamor_composite_with_shader(CARD8 op, &source_y_off); pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); - glamor_picture_get_matrixf(source, src_matrix); + if (source->transform) { + psrc_matrix = src_matrix; + glamor_picture_get_matrixf(source, psrc_matrix); + } vert_stride += 4; } @@ -1226,7 +1263,10 @@ glamor_composite_with_shader(CARD8 op, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); - glamor_picture_get_matrixf(mask, mask_matrix); + if (mask->transform) { + pmask_matrix = mask_matrix; + glamor_picture_get_matrixf(mask, pmask_matrix); + } vert_stride += 4; } @@ -1252,13 +1292,16 @@ glamor_composite_with_shader(CARD8 op, x_dest = rects->x_dst + dest_x_off; y_dest = rects->y_dst + dest_y_off; - x_source = rects->x_src + source_x_off;; + x_source = rects->x_src + source_x_off; y_source = rects->y_src + source_y_off; x_mask = rects->x_mask + mask_x_off; y_mask = rects->y_mask + mask_y_off; width = rects->width; height = rects->height; + DEBUGF("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", + x_dest, y_dest, x_source, y_source,x_mask,y_mask,width,height); + glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale, dst_yscale, x_dest, y_dest, @@ -1266,41 +1309,21 @@ glamor_composite_with_shader(CARD8 op, glamor_priv->yInverted, vertices); - if (key.source != SHADER_SOURCE_SOLID) { - if (source->transform) - glamor_set_transformed_normalize_tcoords - (source_pixmap_priv, src_matrix, src_xscale, - src_yscale, x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, - source_texcoords); - else - glamor_set_normalize_tcoords - (source_pixmap_priv, src_xscale, src_yscale, - x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, - source_texcoords); - } + if (key.source != SHADER_SOURCE_SOLID) + glamor_set_normalize_tcoords_generic( + source_pixmap_priv, source->repeatType, psrc_matrix, + src_xscale, src_yscale, x_source, y_source, + x_source + width, y_source + height, + glamor_priv->yInverted, source_texcoords); if (key.mask != SHADER_MASK_NONE - && key.mask != SHADER_MASK_SOLID) { - if (mask->transform) - glamor_set_transformed_normalize_tcoords - (mask_pixmap_priv, mask_matrix, - mask_xscale, - mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, - mask_texcoords); - else - glamor_set_normalize_tcoords - (mask_pixmap_priv, mask_xscale, - mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, - mask_texcoords); - } + && key.mask != SHADER_MASK_SOLID) + glamor_set_normalize_tcoords_generic( + mask_pixmap_priv, mask->repeatType, pmask_matrix, + mask_xscale, mask_yscale, x_mask, y_mask, + x_mask + width, y_mask + height, + glamor_priv->yInverted, mask_texcoords); + glamor_emit_composite_rect(screen, source_texcoords, mask_texcoords, @@ -1323,6 +1346,7 @@ glamor_composite_with_shader(CARD8 op, dispatch->glActiveTexture(GL_TEXTURE1); dispatch->glDisable(GL_TEXTURE_2D); #endif + DEBUGF("finish rendering.\n"); dispatch->glUseProgram(0); if (saved_source_format) source->format = saved_source_format; @@ -1398,17 +1422,18 @@ glamor_convert_gradient_picture(ScreenPtr screen, return dst; } -static Bool -_glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height, Bool fallback) +Bool +glamor_composite_clipped_region(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + RegionPtr region, + int x_source, + int y_source, + int x_mask, + int y_mask, + int x_dest, + int y_dest) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_pixmap_private *dest_pixmap_priv; @@ -1419,80 +1444,63 @@ _glamor_composite(CARD8 op, PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; PicturePtr temp_src = source, temp_mask = mask; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; + + BoxPtr extent; glamor_composite_rect_t rect[10]; glamor_composite_rect_t *prect = rect; int prect_size = ARRAY_SIZE(rect); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - Bool ret = TRUE; - RegionRec region; + int ok = FALSE; + int i; + int width; + int height; BoxPtr box; - int nbox, i, ok = FALSE; - PixmapPtr sub_dest_pixmap = NULL; - PixmapPtr sub_source_pixmap = NULL; - PixmapPtr sub_mask_pixmap = NULL; - int dest_x_off, dest_y_off, saved_dest_x = 0, saved_dest_y = 0; - int source_x_off, source_y_off, saved_source_x = 0, saved_source_y = 0; - int mask_x_off, mask_y_off, saved_mask_x = 0, saved_mask_y = 0; - DrawablePtr saved_dest_drawable = NULL; - DrawablePtr saved_source_drawable = NULL; - DrawablePtr saved_mask_drawable = NULL; + int nbox; + extent = RegionExtents(region); + box = RegionRects(region); + nbox = RegionNumRects(region); + width = extent->x2 - extent->x1; + height = extent->y2 - extent->y1; x_temp_src = x_source; y_temp_src = y_source; x_temp_mask = x_mask; y_temp_mask = y_mask; - - DEBUGF("Composite Src: (%d, %d)\n" - " Mask: (%d, %d)\n" - " to dst: (%d, %d), size: %d X %d \n", - x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", + x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + DEBUGF("dest pixmap %p ", dest_pixmap); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ - if (source->pDrawable) { + if (source && source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) - goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) - goto fail; } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - goto fail; - } - - if (op >= ARRAY_SIZE(composite_op_info)) - goto fail; - - if ((!source->pDrawable + /* XXX is it possible source mask have non-zero drawable.x/y? */ + if (source + && ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) - && - ((width * height * 4 < - (source_pixmap->drawable.width * - source_pixmap->drawable.height)) - || - !(glamor_check_fbo_size - (glamor_priv, source_pixmap->drawable.width, - source_pixmap->drawable.height))))) { + && (source_pixmap->drawable.width != width + || source_pixmap->drawable.height != height)))) { temp_src = glamor_convert_gradient_picture(screen, source, - x_source, y_source, + extent->x1 + x_source - x_dest, + extent->y1 + y_source - y_dest, width, height); if (!temp_src) { temp_src = source; - goto fail; + goto out; } - x_temp_src = y_temp_src = 0; + x_temp_src = - extent->x1 + x_dest; + y_temp_src = - extent->y1 + y_dest; } if (mask @@ -1500,26 +1508,22 @@ _glamor_composite(CARD8 op, ((!mask->pDrawable && (mask->pSourcePict->type != SourcePictTypeSolidFill)) || (mask->pDrawable - && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) - && - ((width * height * 4 < - (mask_pixmap->drawable.width * - mask_pixmap->drawable.height)) - || - !(glamor_check_fbo_size - (glamor_priv, mask_pixmap->drawable.width, - mask_pixmap->drawable.height)))))) { + && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv) + && (mask_pixmap->drawable.width != width + || mask_pixmap->drawable.height != height)))) { /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity * to do reduce one convertion. */ temp_mask = glamor_convert_gradient_picture(screen, mask, - x_mask, y_mask, + extent->x1 + x_mask - x_dest, + extent->y1 + y_mask - y_dest, width, height); if (!temp_mask) { temp_mask = mask; - goto fail; + goto out; } - x_temp_mask = y_temp_mask = 0; + x_temp_mask = - extent->x1 + x_dest; + y_temp_mask = - extent->y1 + y_dest; } /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. @@ -1527,43 +1531,38 @@ _glamor_composite(CARD8 op, if (mask && mask->componentAlpha) { if (op == PictOpOver) { - glamor_composite(PictOpOutReverse, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, width, height); - glamor_composite(PictOpAdd, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, width, height); - goto done; + glamor_composite_clipped_region(PictOpOutReverse, + temp_src, temp_mask, dest, + region, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, + x_dest, y_dest); - } else if (op == PictOpAtop - || op == PictOpAtopReverse - || op == PictOpXor - || op >= PictOpSaturate) { - glamor_fallback - ("glamor_composite(): component alpha op %x\n", op); - goto fail; + glamor_composite_clipped_region(PictOpAdd, + temp_src, temp_mask, dest, + region, + x_temp_src, y_temp_src, + x_temp_mask, y_temp_mask, + x_dest, y_dest); + ok = TRUE; + goto out; } } - if (!mask) { + if (!mask && temp_src) { if (glamor_composite_with_copy(op, temp_src, dest, x_temp_src, y_temp_src, - x_dest, y_dest, width, - height)) - goto done; + x_dest, y_dest, region)) { + ok = TRUE; + goto out; + } } - /*XXXXX, maybe we can make a copy of dest pixmap.*/ - if (source_pixmap == dest_pixmap) - goto full_fallback; + /*XXXXX, self copy?*/ x_dest += dest->pDrawable->x; y_dest += dest->pDrawable->y; - if (temp_src->pDrawable) { + if (temp_src && temp_src->pDrawable) { x_temp_src += temp_src->pDrawable->x; y_temp_src += temp_src->pDrawable->y; } @@ -1571,16 +1570,6 @@ _glamor_composite(CARD8 op, x_temp_mask += temp_mask->pDrawable->x; y_temp_mask += temp_mask->pDrawable->y; } - if (!miComputeCompositeRegion(®ion, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, width, - height)) - goto done; - - box = REGION_RECTS(®ion); - nbox = REGION_NUM_RECTS(®ion); if (nbox > ARRAY_SIZE(rect)) { prect = calloc(nbox, sizeof(*prect)); @@ -1612,15 +1601,153 @@ _glamor_composite(CARD8 op, box += box_cnt; } + if (prect != rect) + free(prect); +out: + if (temp_src != source) + FreePicture(temp_src, 0); + if (temp_mask != mask) + FreePicture(temp_mask, 0); + + return ok; +} + +static Bool +_glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height, Bool fallback) +{ + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_pixmap_private *dest_pixmap_priv; + glamor_pixmap_private *source_pixmap_priv = + NULL, *mask_pixmap_priv = NULL; + PixmapPtr dest_pixmap = + glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + Bool ret = TRUE; + RegionRec region; + BoxPtr box, extent; + int nbox, ok = FALSE; + PixmapPtr sub_dest_pixmap = NULL; + PixmapPtr sub_source_pixmap = NULL; + PixmapPtr sub_mask_pixmap = NULL; + int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y; + int source_x_off, source_y_off, saved_source_x, saved_source_y; + int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y; + DrawablePtr saved_dest_drawable; + DrawablePtr saved_source_drawable; + DrawablePtr saved_mask_drawable; + int force_clip = 0; + + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + + if (source->pDrawable) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; + } + + if (mask && mask->pDrawable) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; + } + + DEBUGF("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n", + source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + goto fail; + } + + if (op >= ARRAY_SIZE(composite_op_info)) + goto fail; + + if (mask && mask->componentAlpha) { + if (op == PictOpAtop + || op == PictOpAtopReverse + || op == PictOpXor + || op >= PictOpSaturate) { + glamor_fallback + ("glamor_composite(): component alpha op %x\n", op); + goto fail; + } + } + + if (!miComputeCompositeRegion(®ion, + source, mask, dest, + x_source + (source_pixmap ? source->pDrawable->x : 0), + y_source + (source_pixmap ? source->pDrawable->y : 0), + x_mask + (mask_pixmap ? mask->pDrawable->x : 0), + y_mask + (mask_pixmap ? mask->pDrawable->y : 0), + x_dest + dest->pDrawable->x, + y_dest + dest->pDrawable->y, + width, + height)) { + ret = TRUE; + goto done; + } + + box = REGION_RECTS(®ion); + nbox = REGION_NUM_RECTS(®ion); + DEBUGF("first clipped when compositing.\n"); + DEBUGRegionPrint(®ion); + extent = RegionExtents(®ion); + if (nbox == 0) { + ret = TRUE; + goto done; + } + /* If destination is not a large pixmap, but the region is larger + * than texture size limitation, and source or mask is memory pixmap, + * then there may be need to load a large memory pixmap to a + * texture, and this is not permitted. Then we force to clip the + * destination and make sure latter will not upload a large memory + * pixmap. */ + if (!glamor_check_fbo_size(glamor_priv, + extent->x2 - extent->x1, extent->y2 - extent->y1) + && (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) + && ((source_pixmap_priv + && source_pixmap_priv->type == GLAMOR_MEMORY) + || (mask_pixmap_priv + && mask_pixmap_priv->type == GLAMOR_MEMORY) + || (!source_pixmap_priv + && (source->pSourcePict->type != SourcePictTypeSolidFill)) + || (!mask_pixmap_priv && mask + && mask->pSourcePict->type != SourcePictTypeSolidFill))) + force_clip = 1; + + if (force_clip || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + || (source_pixmap_priv + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) + || (mask_pixmap_priv + && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) + goto fail; + else + ok = glamor_composite_clipped_region(op, source, + mask, dest, ®ion, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest); + REGION_UNINIT(dest->pDrawable->pScreen, ®ion); if (ok) goto done; - fail: if (!fallback && glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable) - && (!source_pixmap + && (!source_pixmap || glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable)) && (!mask_pixmap || glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) { @@ -1662,13 +1789,11 @@ fail: x_ ##p = 0; \ y_ ##p = 0; \ } } while(0) - GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); - if (source->pDrawable) + if (source->pDrawable && !source->transform) GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); - if (mask && mask->pDrawable) + if (mask && mask->pDrawable && !mask->transform) GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); - full_fallback: if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (source_pixmap == dest_pixmap || glamor_prepare_access_picture @@ -1711,12 +1836,6 @@ full_fallback: PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO); PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); done: - if (temp_src != source) - FreePicture(temp_src, 0); - if (temp_mask != mask) - FreePicture(temp_mask, 0); - if (prect != rect) - free(prect); return ret; } @@ -1754,9 +1873,6 @@ glamor_composite_nf(CARD8 op, FALSE); } - - - /** * Creates an appropriate picture to upload our alpha mask into (which * we calculated in system memory) @@ -1797,7 +1913,7 @@ glamor_create_mask_picture(ScreenPtr screen, * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid * accumulation in system memory. */ -static Bool +static Bool _glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, @@ -1885,7 +2001,7 @@ glamor_trapezoids(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps) { - _glamor_trapezoids(op, src, dst, mask_format, x_src, + _glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, ntrap, traps, TRUE); } @@ -1895,7 +2011,7 @@ glamor_trapezoids_nf(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps) { - return _glamor_trapezoids(op, src, dst, mask_format, x_src, + return _glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, ntrap, traps, FALSE); } @@ -1912,8 +2028,12 @@ glamor_composite_glyph_rects(CARD8 op, ValidatePicture(src); ValidatePicture(dst); - if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) - return; + if (!(glamor_is_large_picture(src) + || (mask && glamor_is_large_picture(mask)) + || glamor_is_large_picture(dst))) { + if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) + return; + } n = nrect; r = rects; diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index c6b88d267..871479bd0 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -102,10 +102,9 @@ glamor_fini_tile_shader(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } -Bool -glamor_tile(PixmapPtr pixmap, PixmapPtr tile, +static void +_glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, int tile_x, int tile_y) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -126,48 +125,17 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; float wh[2]; - src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); - if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL) - goto fail; - - if (glamor_priv->tile_prog == 0) { - glamor_fallback("Tiling unsupported\n"); - goto fail; - } - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest has no fbo.\n"); - goto fail; - } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { - /* XXX dynamic uploading candidate. */ - glamor_fallback("Non-texture tile pixmap\n"); - goto fail; - } - - if (!glamor_set_planemask(pixmap, planemask)) { - glamor_fallback("unsupported planemask %lx\n", planemask); - goto fail; - } - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - - dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, alu)) { - glamor_put_dispatch(glamor_priv); - goto fail; - } - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glUseProgram(glamor_priv->tile_prog); glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv); - dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, @@ -185,21 +153,23 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, - src_yscale, - tile_x1, tile_y1, - tile_x2, tile_y2, - glamor_priv->yInverted, - source_texcoords); + glamor_set_repeat_normalize_tcoords + (src_pixmap_priv, RepeatNormal, + src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), source_texcoords); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, - dst_yscale, - x1, y1, x2, y2, + glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale, + x1, y1, + x2, y2, glamor_priv->yInverted, vertices); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -214,11 +184,139 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, #endif dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); +} + +Bool +glamor_tile(PixmapPtr pixmap, PixmapPtr tile, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + int tile_x, int tile_y) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *dst_pixmap_priv; + glamor_pixmap_private *src_pixmap_priv; + glamor_gl_dispatch *dispatch; + + dst_pixmap_priv = glamor_get_pixmap_private(pixmap); + src_pixmap_priv = glamor_get_pixmap_private(tile); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) + return FALSE; + + if (glamor_priv->tile_prog == 0) { + glamor_fallback("Tiling unsupported\n"); + goto fail; + } + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { + /* XXX dynamic uploading candidate. */ + glamor_fallback("Non-texture tile pixmap\n"); + goto fail; + } + + if (!glamor_set_planemask(pixmap, planemask)) { + glamor_fallback("unsupported planemask %lx\n", planemask); + goto fail; + } + + dispatch = glamor_get_dispatch(glamor_priv); + if (!glamor_set_alu(dispatch, alu)) { + glamor_fallback("unsupported alu %x\n", alu); + glamor_put_dispatch(glamor_priv); + goto fail; + } + + if (dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + glamor_pixmap_clipped_regions *clipped_dst_regions; + int n_dst_region, i, j, k; + BoxRec box; + RegionRec region; + + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + RegionInitBoxes(®ion, &box, 1); + clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, + ®ion, &n_dst_region, 0); + for(i = 0; i < n_dst_region; i++) + { + int n_src_region; + glamor_pixmap_clipped_regions *clipped_src_regions; + BoxPtr current_boxes; + int n_current_boxes; + + SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, clipped_dst_regions[i].block_idx); + + if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionTranslate(clipped_dst_regions[i].region, + tile_x - x, tile_y - y); + DEBUGF("tiled a large src pixmap. %dx%d \n", tile->drawable.width, tile->drawable.height); + clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, + clipped_dst_regions[i].region, + &n_src_region, 1); + DEBUGF("got %d src regions %d \n", n_src_region); + for (j = 0; j < n_src_region; j++) + { + + SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx); + + RegionTranslate(clipped_src_regions[j].region, + x - tile_x, + y - tile_y); + current_boxes = RegionRects(clipped_src_regions[j].region); + n_current_boxes = RegionNumRects(clipped_src_regions[j].region); + for(k = 0; k < n_current_boxes; k++) + { + DEBUGF("Tile on %d %d %d %d dst block id %d tile block id %d tilex %d tiley %d\n", + current_boxes[k].x1, current_boxes[k].y1, + current_boxes[k].x2 - current_boxes[k].x1, + current_boxes[k].y2 - current_boxes[k].y1, + clipped_dst_regions[i].block_idx, + clipped_src_regions[j].block_idx, + (tile_x + (current_boxes[k].x1 - x)), + tile_y + (current_boxes[k].y1 - y)); + + _glamor_tile(pixmap, tile, + current_boxes[k].x1, current_boxes[k].y1, + current_boxes[k].x2 - current_boxes[k].x1, + current_boxes[k].y2 - current_boxes[k].y1, + (tile_x + (current_boxes[k].x1 - x)), + (tile_y + (current_boxes[k].y1 - y))); + } + + RegionDestroy(clipped_src_regions[j].region); + } + free(clipped_src_regions); + } else { + current_boxes = RegionRects(clipped_dst_regions[i].region); + n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); + for(k = 0; k < n_current_boxes; k++) + { + _glamor_tile(pixmap, tile, + current_boxes[k].x1, current_boxes[k].y1, + current_boxes[k].x2 - current_boxes[k].x1, + current_boxes[k].y2 - current_boxes[k].y1, + (tile_x + (current_boxes[k].x1 - x)), + (tile_y + (current_boxes[k].y1 - y))); + } + } + RegionDestroy(clipped_dst_regions[i].region); + } + free(clipped_dst_regions); + RegionUninit(®ion); + } + else + _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y); + glamor_set_alu(dispatch, GXcopy); - glamor_set_planemask(pixmap, ~0); glamor_put_dispatch(glamor_priv); return TRUE; - - fail: +fail: return FALSE; + } diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 90a1657e6..44c8175ae 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -41,8 +41,10 @@ #define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height; \ + int w,h; \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \ + *(_pxscale_) = 1.0 / w; \ + *(_pyscale_) = 1.0 / h; \ } while(0) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ @@ -106,6 +108,52 @@ } \ } while(0) +#define _glamor_get_repeat_coords(priv, repeat_type, tx1, \ + ty1, tx2, ty2, \ + _x1_, _y1_, _x2_, \ + _y2_, c, d, odd_x, odd_y) \ + do { \ + if (repeat_type == RepeatReflect) { \ + assert(0); \ + } else if (repeat_type == RepeatNormal) { \ + tx1 = (c - priv->box.x1); \ + ty1 = (d - priv->box.y1); \ + tx2 = tx1 + ((_x2_) - (_x1_)); \ + ty2 = ty1 + ((_y2_) - (_y1_)); \ + } else { \ + assert(0); \ + } \ + } while(0) + + + +/* _x1_ ... _y2_ must be integer. */ +#define glamor_get_repeat_coords(priv, repeat_type, tx1, \ + ty1, tx2, ty2, _x1_, _y1_, _x2_, \ + _y2_) \ + do { \ + int c, d; \ + int odd_x = 0, odd_y = 0; \ + DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \ + (priv)->base.pixmap->drawable.width, \ + priv->box.x1, priv->box.x2, \ + priv->box.y1, priv->box.y2); \ + modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \ + modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \ + DEBUGF("c %d d %d \n", c, d); \ + if (repeat_type == RepeatReflect) { \ + odd_x = abs((_x1_ - c) \ + / (priv->base.pixmap->drawable.width)) & 1; \ + odd_y = abs((_y1_ - d) \ + / (priv->base.pixmap->drawable.height)) & 1; \ + } \ + _glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\ + _x1_, _y1_, _x2_, _y2_, c, d, \ + odd_x, odd_y); \ + } while(0) + + + #define glamor_transform_point(matrix, tx, ty, x, y) \ do { \ int i; \ @@ -213,6 +261,24 @@ tx2, ty2, yInverted, vertices); \ } while(0) +#define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \ + xscale, yscale, \ + _x1_, _y1_, _x2_, _y2_, \ + yInverted, vertices) \ + do { \ + float tx1, tx2, ty1, ty2; \ + if (priv->type == GLAMOR_TEXTURE_LARGE) \ + glamor_get_repeat_coords((&priv->large), repeat_type, \ + tx1, ty1, tx2, ty2, \ + _x1_, _y1_, _x2_, _y2_); \ + else { \ + tx1 = _x1_; tx2 = _x2_; ty1 = _y1_; ty2 = _y2_; \ + } \ + _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ + tx2, ty2, yInverted, vertices); \ + } while(0) + + #define glamor_set_tcoords(width, height, x1, y1, x2, y2, \ yInverted, vertices) \ do { \ @@ -303,7 +369,7 @@ glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) } inline static void -glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) +glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy) { int i; for (i = 0; i < nbox; i++) { From eb6f981ba4d3a4aff1b3651bdad3cd7a52233b41 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 02:15:53 +0800 Subject: [PATCH 382/462] largepixmap: Enable glamor_composite. Now we start to enable glamor_composite on large pixmap. We need to do a three layer clipping to split the dest/source/mask to small pieces. This commit only support non-transformation and repeat normal case. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 2 +- glamor/glamor_largepixmap.c | 183 ++++++++++++++++++++++++++++++++++++ glamor/glamor_render.c | 12 ++- 3 files changed, 195 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index fe7d9de26..dd3b4c625 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -62,7 +62,7 @@ */ #define GLYPH_BUFFER_SIZE 1024 -#define CACHE_PICTURE_SIZE 1024 +#define CACHE_PICTURE_SIZE 1024 #define GLYPH_MIN_SIZE 8 #define GLYPH_MAX_SIZE 64 #define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c index e8c103056..a1a73a44e 100644 --- a/glamor/glamor_largepixmap.c +++ b/glamor/glamor_largepixmap.c @@ -410,3 +410,186 @@ glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, in { return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0); } + +Bool +glamor_composite_largepixmap_region(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private * source_pixmap_priv, + glamor_pixmap_private * mask_pixmap_priv, + glamor_pixmap_private * dest_pixmap_priv, + RegionPtr region, Bool force_clip, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height) +{ + glamor_screen_private *glamor_priv; + glamor_pixmap_clipped_regions *clipped_dest_regions; + glamor_pixmap_clipped_regions *clipped_source_regions; + glamor_pixmap_clipped_regions *clipped_mask_regions; + int n_dest_regions; + int n_mask_regions; + int n_source_regions; + int i,j,k; + int need_clean_source_fbo = 0; + int need_clean_mask_fbo = 0; + int is_normal_source_fbo = 0; + int is_normal_mask_fbo = 0; + int fixed_block_width, fixed_block_height; + int null_source, null_mask; + glamor_pixmap_private * need_free_source_pixmap_priv = NULL; + glamor_pixmap_private * need_free_mask_pixmap_priv = NULL; + int source_repeat_type = 0, mask_repeat_type = 0; + PixmapPtr source_pixmap = NULL; + PixmapPtr mask_pixmap = NULL; + int ok = TRUE; + + if (source_pixmap_priv) { + source_pixmap = source_pixmap_priv->base.pixmap; + if (source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + && (source->transform + || source->repeatType != RepeatNone)) + return FALSE; + } + + if (mask_pixmap_priv) { + mask_pixmap = mask_pixmap_priv->base.pixmap; + if (mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + && (mask->transform + || mask->repeatType != RepeatNone)) + return FALSE; + } + + if (source->repeat) + source_repeat_type = source->repeatType; + else + source_repeat_type = RepeatNone; + + if (mask && mask->repeat) + mask_repeat_type = mask->repeatType; + else + mask_repeat_type = RepeatNone; + + glamor_priv = dest_pixmap_priv->base.glamor_priv; + fixed_block_width = glamor_priv->max_fbo_size; + fixed_block_height = glamor_priv->max_fbo_size; + RegionTranslate(region, -dest->pDrawable->x, + -dest->pDrawable->y); + + if (force_clip) + clipped_dest_regions = glamor_compute_clipped_regions_ext(dest_pixmap_priv, + region, + &n_dest_regions, + fixed_block_width, + fixed_block_height); + else + clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, + region, + &n_dest_regions, + 0); + DEBUGF("dest clipped result %d region: \n", n_dest_regions); + for(i = 0; i < n_dest_regions; i++) + { + DEBUGF("dest region %d idx %d\n", i, clipped_dest_regions[i].block_idx); + DEBUGRegionPrint(clipped_dest_regions[i].region); + SET_PIXMAP_FBO_CURRENT(dest_pixmap_priv, clipped_dest_regions[i].block_idx); + if ( source_pixmap_priv && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionTranslate(clipped_dest_regions[i].region, + x_source - x_dest, + y_source - y_dest); + clipped_source_regions = glamor_compute_clipped_regions(source_pixmap_priv, + clipped_dest_regions[i].region, + &n_source_regions, source_repeat_type); + DEBUGF("source clipped result %d region: \n", n_source_regions); + for(j = 0; j < n_source_regions; j++) + { + SET_PIXMAP_FBO_CURRENT(source_pixmap_priv, + clipped_source_regions[j].block_idx); + + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + DEBUGF("source region %d idx %d\n", j, clipped_source_regions[j].block_idx); + DEBUGRegionPrint(clipped_source_regions[j].region); + RegionTranslate(clipped_source_regions[j].region, + - x_source + x_mask, + - y_source + y_mask); + clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, + clipped_source_regions[j].region, + &n_mask_regions, mask_repeat_type); + DEBUGF("mask clipped result %d region: \n", n_mask_regions); + +#define COMPOSITE_REGION(region) do { \ + if (!glamor_composite_clipped_region(op, \ + source, \ + mask, dest, region, \ + x_source, y_source, x_mask, y_mask, \ + x_dest, y_dest)) { \ + assert(0); \ + } \ + } while(0) + for(k = 0; k < n_mask_regions; k++) + { + DEBUGF("mask region %d idx %d\n", k, clipped_mask_regions[k].block_idx); + DEBUGRegionPrint(clipped_mask_regions[k].region); + SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, + clipped_mask_regions[k].block_idx); + DEBUGF("mask fbo off %d %d \n", + mask_pixmap_priv->large.box.x1, + mask_pixmap_priv->large.box.y1); + DEBUGF("start composite mask hasn't transform.\n"); + RegionTranslate(clipped_mask_regions[k].region, + x_dest - x_mask + dest->pDrawable->x, + y_dest - y_mask + dest->pDrawable->y); + COMPOSITE_REGION(clipped_mask_regions[k].region); + RegionDestroy(clipped_mask_regions[k].region); + } + free(clipped_mask_regions); + } else { + RegionTranslate(clipped_source_regions[j].region, + -x_source + x_dest + dest->pDrawable->x, + -y_source + y_dest + dest->pDrawable->y); + COMPOSITE_REGION(clipped_source_regions[j].region); + } + if (clipped_source_regions && clipped_source_regions[j].region) + RegionDestroy(clipped_source_regions[j].region); + } + free(clipped_source_regions); + } + else { + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionTranslate(clipped_dest_regions[i].region, + x_mask - x_dest, + y_mask - y_dest); + clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, + clipped_dest_regions[i].region, + &n_mask_regions, mask_repeat_type); + for(k = 0; k < n_mask_regions; k++) + { + DEBUGF("mask region %d idx %d\n", k, clipped_mask_regions[k].block_idx); + DEBUGRegionPrint(clipped_mask_regions[k].region); + SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, + clipped_mask_regions[k].block_idx); + RegionTranslate(clipped_mask_regions[k].region, + x_dest - x_mask + dest->pDrawable->x, + y_dest - y_mask + dest->pDrawable->y); + COMPOSITE_REGION(clipped_mask_regions[k].region); + RegionDestroy(clipped_mask_regions[k].region); + } + free(clipped_mask_regions); + } + else { + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, + dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } + } + RegionDestroy(clipped_dest_regions[i].region); + } + free(clipped_dest_regions); + ok = TRUE; + return ok; +} diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 48a5bb3ee..b19d66c6f 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1732,7 +1732,17 @@ _glamor_composite(CARD8 op, && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) || (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) - goto fail; + ok = glamor_composite_largepixmap_region(op, + source, mask, dest, + source_pixmap_priv, + mask_pixmap_priv, + dest_pixmap_priv, + ®ion, force_clip, + x_source, y_source, + x_mask, y_mask, + x_dest, y_dest, + width, height); + else ok = glamor_composite_clipped_region(op, source, mask, dest, ®ion, From 56d6e7a85fbe8e50c38efda0f59f09aac52b769a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 02:24:41 +0800 Subject: [PATCH 383/462] glamor_putimage: Correct the wrong stride value. We should not use the destination pixmap's devkind as the input image data's stride. Signed-off-by: Zhigang Gong --- glamor/glamor_putimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 6d62bd7bc..34e86a147 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -307,7 +307,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_destroy_pixmap(temp_pixmap); } else glamor_upload_sub_pixmap_to_texture(pixmap, x + drawable->x + x_off, y + drawable->y + y_off, - w, h, pixmap->devKind, bits, 0); + w, h, PixmapBytePad(w, depth), bits, 0); ret = TRUE; goto done; From 48916a23a92366128f5a1eeb08949d8d32383c32 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 02:27:00 +0800 Subject: [PATCH 384/462] glamor_getimage: should call miGetimage if failed to get sub-image. Signed-off-by: Zhigang Gong --- glamor/glamor_getimage.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index 655ed94ee..f446c8333 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -45,6 +45,8 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, if (format != ZPixmap) goto fall_back; + pixmap = glamor_get_drawable_pixmap(drawable); + glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); if (!glamor_set_planemask(pixmap, planeMask)) { glamor_fallback @@ -78,7 +80,7 @@ fall_back: y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RO); } else - fbGetImage(drawable, x, y, w, h, format, planeMask, d); + miGetImage(drawable, x, y, w, h, format, planeMask, d); return TRUE; } From 1d2d858b8daacdd349084433a8af60d559fb6a9d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 09:36:56 +0800 Subject: [PATCH 385/462] largepixmap: Add transform/repeat/reflect/pad support. This commit implement almost all the needed functions for the large pixmap support. It's almost complete. Signed-off-by: Zhigang Gong --- glamor/glamor_largepixmap.c | 815 +++++++++++++++++++++++++++++++++--- glamor/glamor_render.c | 12 +- glamor/glamor_utils.h | 229 +++++++++- 3 files changed, 981 insertions(+), 75 deletions(-) diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c index a1a73a44e..31af71150 100644 --- a/glamor/glamor_largepixmap.c +++ b/glamor/glamor_largepixmap.c @@ -199,6 +199,89 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, return result_regions; } +/* + * + * For the repeat pad mode, we can simply convert the region and + * let the out-of-box region can cover the needed edge of the source/mask + * Then apply a normal clip we can get what we want. + */ +static RegionPtr +_glamor_convert_pad_region(RegionPtr region, int w, int h) +{ + RegionPtr pad_region; + int nrect; + BoxPtr box; + int overlap; + + nrect = RegionNumRects(region); + box = RegionRects(region); + pad_region = RegionCreate(NULL, 4); + if (pad_region == NULL) + return NULL; + while(nrect--) { + BoxRec pad_box; + RegionRec temp_region; + pad_box = *box; + if (pad_box.x1 < 0 && pad_box.x2 <= 0) + pad_box.x2 = 1; + else if (pad_box.x1 >= w && pad_box.x2 > w) + pad_box.x1 = w - 1; + if (pad_box.y1 < 0 && pad_box.y2 <=0) + pad_box.y2 = 1; + else if (pad_box.y1 >= h && pad_box.y2 > h) + pad_box.y1 = h - 1; + RegionInitBoxes(&temp_region, &pad_box, 1); + RegionAppend(pad_region, &temp_region); + RegionUninit(&temp_region); + box++; + } + RegionValidate(pad_region, &overlap); + return pad_region; +} + +/* + * For one type of large pixmap, its one direction is not exceed the + * size limitation, and in another word, on one direction it has only + * one block. + * + * This case of reflect repeating, we can optimize it and avoid repeat + * clip on that direction. We can just enlarge the repeat box and can + * cover all the dest region on that direction. But latter, we need to + * fixup the clipped result to get a correct coords for the subsequent + * processing. This function is to do the coords correction. + * + * */ +static void +_glamor_largepixmap_reflect_fixup(short *xy1, short *xy2, int wh) +{ + int odd1, odd2; + int c1, c2; + + if (*xy2 - *xy1 > wh) { + *xy1 = 0; + *xy2 = wh; + return; + } + modulus(*xy1, wh, c1); + odd1 = ((*xy1 - c1) / wh) & 0x1; + modulus(*xy2, wh, c2); + odd2 = ((*xy2 - c2) / wh) & 0x1; + + if (odd1 && odd2) { + *xy1 = wh - c2; + *xy2 = wh - c1; + } else if (odd1 && !odd2) { + *xy1 = 0; + *xy2 = MAX(c2, wh - c1); + } else if (!odd1 && odd2) { + *xy2 = wh; + *xy1 = MIN(c1, wh - c2); + } else { + *xy1 = c1; + *xy2 = c2; + } +} + /** * Clip the boxes regards to each pixmap's block array. * @@ -207,9 +290,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, * * @is_transform: if it is set, it has a transform matrix. * - * XXX Not support repeatPad currently. */ - static glamor_pixmap_clipped_regions * _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, @@ -242,7 +323,16 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, pixmap_width = priv->base.pixmap->drawable.width; pixmap_height = priv->base.pixmap->drawable.height; - if (repeat_type == 0) { + if (repeat_type == 0 || repeat_type == RepeatPad) { + RegionPtr saved_region = NULL; + if (repeat_type == RepeatPad) { + saved_region = region; + region = _glamor_convert_pad_region(saved_region, pixmap_width, pixmap_height); + if (region == NULL) { + *n_region = 0; + return NULL; + } + } clipped_regions = __glamor_compute_clipped_regions(priv->block_w, priv->block_h, priv->block_wcnt, @@ -251,10 +341,9 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, priv->base.pixmap->drawable.height, region, n_region, 0 ); + if (saved_region) + RegionDestroy(region); return clipped_regions; - } else if (repeat_type != RepeatNormal) { - *n_region = 0; - return NULL; } extent = RegionExtents(region); @@ -329,8 +418,10 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, int shift_x; int shift_y; int saved_y1, saved_y2; - int x_idx = 0, y_idx = 0; + int x_idx = 0, y_idx = 0, saved_y_idx = 0; RegionRec temp_region; + BoxRec reflect_repeat_box; + BoxPtr valid_repeat_box; shift_x = (extent->x1 / pixmap_width) * pixmap_width; shift_y = (extent->y1 / pixmap_height) * pixmap_height; @@ -380,12 +471,108 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, RegionUninit(&repeat_region); } } + } else if (repeat_type == RepeatReflect) { + saved_y1 = repeat_box.y1; + saved_y2 = repeat_box.y2; + saved_y_idx = y_idx; + for(; ; repeat_box.x1 += dx, repeat_box.x2 += dx) + { + repeat_box.y1 = saved_y1; + repeat_box.y2 = saved_y2; + y_idx = saved_y_idx; + reflect_repeat_box.x1 = (x_idx & 1) ? + ((2 * x_idx + 1) * dx - repeat_box.x2) : repeat_box.x1; + reflect_repeat_box.x2 = (x_idx & 1) ? + ((2 * x_idx + 1) * dx - repeat_box.x1) : repeat_box.x2; + valid_repeat_box = &reflect_repeat_box; + + if (valid_repeat_box->x1 >= extent->x2) + break; + for( repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2; + ; + repeat_box.y1 += dy, repeat_box.y2 += dy) + { + + DEBUGF("x_idx %d y_idx %d dx %d dy %d\n", x_idx, y_idx, dx, dy); + DEBUGF("repeat box %d %d %d %d \n", + repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2); + + if (priv->block_hcnt > 1) { + reflect_repeat_box.y1 = (y_idx & 1) ? + ((2 * y_idx + 1) * dy - repeat_box.y2) : repeat_box.y1; + reflect_repeat_box.y2 = (y_idx & 1) ? + ((2 * y_idx + 1) * dy - repeat_box.y1) : repeat_box.y2; + } else { + reflect_repeat_box.y1 = repeat_box.y1; + reflect_repeat_box.y2 = repeat_box.y2; + } + + DEBUGF("valid_repeat_box x1 %d y1 %d \n", + valid_repeat_box->x1, valid_repeat_box->y1); + if (valid_repeat_box->y1 >= extent->y2) + break; + RegionInitBoxes(&repeat_region, valid_repeat_box, 1); + DEBUGF("start to clip repeat[reflect] region: \n"); + DEBUGRegionPrint(&repeat_region); + RegionIntersect(&temp_region, &repeat_region, region); + DEBUGF("result:\n"); + DEBUGRegionPrint(&temp_region); + if (is_transform && RegionNumRects(&temp_region)) { + BoxRec temp_box; + BoxPtr temp_extent; + temp_extent = RegionExtents(&temp_region); + if (priv->block_wcnt > 1) { + if (x_idx & 1) { + temp_box.x1 = ((2 * x_idx + 1)*dx - temp_extent->x2); + temp_box.x2 = ((2 * x_idx + 1)*dx - temp_extent->x1); + } else { + temp_box.x1 = temp_extent->x1; + temp_box.x2 = temp_extent->x2; + } + modulus(temp_box.x1, pixmap_width, temp_box.x1); + modulus(temp_box.x2, pixmap_width, temp_box.x2); + if (temp_box.x2 == 0) temp_box.x2 = pixmap_width; + } else { + temp_box.x1 = temp_extent->x1; + temp_box.x2 = temp_extent->x2; + _glamor_largepixmap_reflect_fixup(&temp_box.x1, &temp_box.x2, pixmap_width); + } + + if (priv->block_hcnt > 1) { + if (y_idx & 1) { + temp_box.y1 = ((2 * y_idx + 1)*dy - temp_extent->y2); + temp_box.y2 = ((2 * y_idx + 1)*dy - temp_extent->y1); + } else { + temp_box.y1 = temp_extent->y1; + temp_box.y2 = temp_extent->y2; + } + + modulus(temp_box.y1, pixmap_height, temp_box.y1); + modulus(temp_box.y2, pixmap_height, temp_box.y2); + if (temp_box.y2 == 0) temp_box.y2 = pixmap_height; + } else { + temp_box.y1 = temp_extent->y1; + temp_box.y2 = temp_extent->y2; + _glamor_largepixmap_reflect_fixup(&temp_box.y1, &temp_box.y2, pixmap_height); + } + + RegionInitBoxes(&temp_region, &temp_box, 1); + RegionTranslate(&temp_region, x_center_shift * pixmap_width, y_center_shift * pixmap_height); + DEBUGF("for transform result:\n"); + DEBUGRegionPrint(&temp_region); + } + RegionAppend(current_region, &temp_region); + RegionUninit(&repeat_region); + y_idx++; + } + x_idx++; + } } DEBUGF("dx %d dy %d \n", dx, dy); if (RegionNumRects(current_region)) { - if ((right_shift != 0 || down_shift != 0)) + if ((right_shift != 0 || down_shift != 0) && !(is_transform && repeat_type == RepeatReflect)) RegionTranslate(current_region, -right_shift * pixmap_width, -down_shift * pixmap_height); @@ -411,6 +598,323 @@ glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, in return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0); } +/* XXX overflow still exist. maybe we need to change to use region32. + * by default. Or just use region32 for repeat cases? + **/ +glamor_pixmap_clipped_regions * +glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, + RegionPtr region, int *n_region, int dx, int dy, int repeat_type) +{ + BoxPtr temp_extent; + struct pixman_box32 temp_box; + struct pixman_box16 short_box; + RegionPtr temp_region; + glamor_pixmap_clipped_regions *ret; + + temp_region = RegionCreate(NULL, 4); + temp_extent = RegionExtents(region); + DEBUGF("dest region \n"); + DEBUGRegionPrint(region); + /* dx/dy may exceed MAX SHORT. we have to use + * a box32 to represent it.*/ + temp_box.x1 = temp_extent->x1 + dx; + temp_box.x2 = temp_extent->x2 + dx; + temp_box.y1 = temp_extent->y1 + dy; + temp_box.y2 = temp_extent->y2 + dy; + + DEBUGF("source box %d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, temp_box.y2); + if (transform) + glamor_get_transform_extent_from_box(&temp_box, transform); + if (repeat_type == RepeatNone) { + if (temp_box.x1 < 0) temp_box.x1 = 0; + if (temp_box.y1 < 0) temp_box.y1 = 0; + temp_box.x2 = MIN(temp_box.x2, priv->base.pixmap->drawable.width); + temp_box.y2 = MIN(temp_box.y2, priv->base.pixmap->drawable.height); + } + /* Now copy back the box32 to a box16 box. */ + short_box.x1 = temp_box.x1; + short_box.y1 = temp_box.y1; + short_box.x2 = temp_box.x2; + short_box.y2 = temp_box.y2; + RegionInitBoxes(temp_region, &short_box, 1); + DEBUGF("copy to temp source region \n"); + DEBUGRegionPrint(temp_region); + ret = _glamor_compute_clipped_regions(priv, + temp_region, + n_region, + repeat_type, + 1); + DEBUGF("n_regions = %d \n", *n_region); + RegionDestroy(temp_region); + + return ret; +} +/* + * As transform and repeatpad mode. + * We may get a clipped result which in multipe regions. + * It's not easy to do a 2nd round clipping just as we do + * without transform/repeatPad. As it's not easy to reverse + * the 2nd round clipping result with a transform/repeatPad mode, + * or even impossible for some transformation. + * + * So we have to merge the fragmental region into one region + * if the clipped result cross the region boundary. + */ +static void +glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, int repeat_type, + glamor_pixmap_clipped_regions *clipped_regions, + int *n_regions, int *need_clean_fbo) +{ + BoxPtr temp_extent; + BoxRec temp_box, copy_box; + RegionPtr temp_region; + glamor_pixmap_private *temp_priv; + PixmapPtr temp_pixmap; + int overlap; + int i; + int pixmap_width, pixmap_height; + glamor_pixmap_private_large_t *priv; + + priv = &pixmap_priv->large; + pixmap_width = priv->base.pixmap->drawable.width; + pixmap_height = priv->base.pixmap->drawable.height; + + temp_region = RegionCreate(NULL, 4); + for(i = 0; i < *n_regions; i++) + { + DEBUGF("Region %d:\n", i); + DEBUGRegionPrint(clipped_regions[i].region); + RegionAppend(temp_region, clipped_regions[i].region); + } + + RegionValidate(temp_region, &overlap); + DEBUGF("temp region: \n"); + DEBUGRegionPrint(temp_region); + temp_extent = RegionExtents(temp_region); + + temp_box = *temp_extent; + + DEBUGF("need copy region: \n"); + DEBUGF("%d %d %d %d \n", temp_box.x1, temp_box.y1, temp_box.x2, temp_box.y2); + temp_pixmap = glamor_create_pixmap(priv->base.pixmap->drawable.pScreen, + temp_box.x2 - temp_box.x1, + temp_box.y2 - temp_box.y1, + priv->base.pixmap->drawable.depth, + GLAMOR_CREATE_PIXMAP_FIXUP); + if (temp_pixmap == NULL) { + assert(0); + return; + } + + temp_priv = glamor_get_pixmap_private(temp_pixmap); + assert(temp_priv->type != GLAMOR_TEXTURE_LARGE); + + priv->box = temp_box; + if (temp_extent->x1 >= 0 && temp_extent->x2 <= pixmap_width + && temp_extent->y1 >= 0 && temp_extent->y2 <= pixmap_height) { + int dx, dy; + copy_box.x1 = 0; + copy_box.y1 = 0; + copy_box.x2 = temp_extent->x2 - temp_extent->x1; + copy_box.y2 = temp_extent->y2 - temp_extent->y1; + dx = temp_extent->x1; + dy = temp_extent->y1; + glamor_copy_n_to_n(&priv->base.pixmap->drawable, + &temp_pixmap->drawable, + NULL, ©_box, 1, dx, + dy, 0, 0, 0, NULL); +// glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, +// temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00); + } else { + for (i = 0; i < *n_regions; i++) + { + BoxPtr box; + int nbox; + box = REGION_RECTS(clipped_regions[i].region); + nbox = REGION_NUM_RECTS(clipped_regions[i].region); + while(nbox--) { + int dx, dy, c, d; + DEBUGF("box x1 %d y1 %d x2 %d y2 %d \n", + box->x1, box->y1, box->x2, box->y2); + modulus(box->x1, pixmap_width, c); + dx = c - (box->x1 - temp_box.x1); + copy_box.x1 = box->x1 - temp_box.x1; + copy_box.x2 = box->x2 - temp_box.x1; + + modulus(box->y1, pixmap_height, d); + dy = d - (box->y1 - temp_box.y1); + copy_box.y1 = box->y1 - temp_box.y1; + copy_box.y2 = box->y2 - temp_box.y1; + + DEBUGF("copying box %d %d %d %d, dx %d dy %d\n", + copy_box.x1, copy_box.y1, copy_box.x2, + copy_box.y2, dx, dy); + + glamor_copy_n_to_n(&priv->base.pixmap->drawable, + &temp_pixmap->drawable, + NULL, ©_box, 1, dx, + dy, 0, 0, 0, NULL); + box++; + } + } + //glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, + // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff); + } + /* The first region will be released at caller side. */ + for(i = 1; i < *n_regions; i++) + RegionDestroy(clipped_regions[i].region); + RegionDestroy(temp_region); + priv->box = temp_box; + priv->base.fbo = glamor_pixmap_detach_fbo(temp_priv); + DEBUGF("priv box x1 %d y1 %d x2 %d y2 %d \n", + priv->box.x1, priv->box.y1, priv->box.x2, priv->box.y2); + glamor_destroy_pixmap(temp_pixmap); + *need_clean_fbo = 1; + *n_regions = 1; +} + + + +/** + * Given an expected transformed block width and block height, + * + * This function calculate a new block width and height which + * guarantee the transform result will not exceed the given + * block width and height. + * + * For large block width and height (> 2048), we choose a + * smaller new width and height and to reduce the cross region + * boundary and can avoid some overhead. + * + **/ +Bool +glamor_get_transform_block_size(struct pixman_transform *transform, + int block_w, int block_h, + int *transformed_block_w, + int *transformed_block_h) +{ + double a,b,c,d,e,f,g,h; + double scale; + int width, height; + a = pixman_fixed_to_double(transform->matrix[0][0]); + b = pixman_fixed_to_double(transform->matrix[0][1]); + c = pixman_fixed_to_double(transform->matrix[1][0]); + d = pixman_fixed_to_double(transform->matrix[1][1]); + scale = pixman_fixed_to_double(transform->matrix[2][2]); + if (block_w > 2048) { + /* For large block size, we shrink it to smaller box, + * thus latter we may get less cross boundary regions and + * thus can avoid some extra copy. + * + **/ + width = block_w / 4; + height = block_h / 4; + } else { + width = block_w - 2; + height = block_h - 2; + } + e = a + b; + f = c + d; + + g = a - b; + h = c - d; + + e = MIN(block_w, floor(width * scale) / MAX(fabs(e), fabs(g))); + f = MIN(block_h, floor(height * scale) / MAX(fabs(f), fabs(h))); + *transformed_block_w = MIN(e, f) - 1; + *transformed_block_h = *transformed_block_w; + if (*transformed_block_w <= 0 || *transformed_block_h <= 0) + return FALSE; + DEBUGF("original block_w/h %d %d, fixed %d %d \n", block_w, block_h, + *transformed_block_w, *transformed_block_h); + return TRUE; +} + +#define VECTOR_FROM_POINT(p, x, y) \ + p.v[0] = x; \ + p.v[1] = y; \ + p.v[2] = 1.0; +void +glamor_get_transform_extent_from_box(struct pixman_box32 *box, + struct pixman_transform *transform) +{ + struct pixman_f_vector p0, p1, p2, p3; + float min_x, min_y, max_x, max_y; + + struct pixman_f_transform ftransform; + + VECTOR_FROM_POINT(p0, box->x1, box->y1) + VECTOR_FROM_POINT(p1, box->x2, box->y1) + VECTOR_FROM_POINT(p2, box->x2, box->y2) + VECTOR_FROM_POINT(p3, box->x1, box->y2) + + pixman_f_transform_from_pixman_transform(&ftransform, transform); + pixman_f_transform_point(&ftransform, &p0); + pixman_f_transform_point(&ftransform, &p1); + pixman_f_transform_point(&ftransform, &p2); + pixman_f_transform_point(&ftransform, &p3); + + min_x = MIN(p0.v[0], p1.v[0]); + min_x = MIN(min_x, p2.v[0]); + min_x = MIN(min_x, p3.v[0]); + + min_y = MIN(p0.v[1], p1.v[1]); + min_y = MIN(min_y, p2.v[1]); + min_y = MIN(min_y, p3.v[1]); + + max_x = MAX(p0.v[0], p1.v[0]); + max_x = MAX(max_x, p2.v[0]); + max_x = MAX(max_x, p3.v[0]); + + max_y = MAX(p0.v[1], p1.v[1]); + max_y = MAX(max_y, p2.v[1]); + max_y = MAX(max_y, p3.v[1]); + box->x1 = floor(min_x) - 1; + box->y1 = floor(min_y) - 1; + box->x2 = ceil(max_x) + 1; + box->y2 = ceil(max_y) + 1; +} + +static void +_glamor_process_transformed_clipped_region(glamor_pixmap_private *priv, + int repeat_type, + glamor_pixmap_clipped_regions *clipped_regions, + int *n_regions, int *need_clean_fbo) +{ + int shift_x, shift_y; + if (*n_regions != 1) { + /* Merge all source regions into one region. */ + glamor_merge_clipped_regions(priv, repeat_type, + clipped_regions, n_regions, + need_clean_fbo); + } else { + SET_PIXMAP_FBO_CURRENT(priv, + clipped_regions[0].block_idx); + if (repeat_type == RepeatReflect || repeat_type == RepeatNormal) { + /* The required source areas are in one region, + * we need to shift the corresponding box's coords to proper position, + * thus we can calculate the relative coords correctly.*/ + BoxPtr temp_box; + int rem; + temp_box = RegionExtents(clipped_regions[0].region); + modulus(temp_box->x1, priv->base.pixmap->drawable.width, rem); + shift_x = (temp_box->x1 - rem) / priv->base.pixmap->drawable.width; + modulus(temp_box->y1, priv->base.pixmap->drawable.height, rem); + shift_y = (temp_box->y1 - rem) / priv->base.pixmap->drawable.height; + + if (shift_x != 0) { + priv->large.box.x1 += shift_x * priv->base.pixmap->drawable.width; + priv->large.box.x2 += shift_x * priv->base.pixmap->drawable.width; + } + if (shift_y != 0) { + priv->large.box.y1 += shift_y * priv->base.pixmap->drawable.height; + priv->large.box.y2 += shift_y * priv->base.pixmap->drawable.height; + } + } + } +} + + Bool glamor_composite_largepixmap_region(CARD8 op, PicturePtr source, @@ -448,21 +952,11 @@ glamor_composite_largepixmap_region(CARD8 op, PixmapPtr mask_pixmap = NULL; int ok = TRUE; - if (source_pixmap_priv) { + if (source_pixmap_priv) source_pixmap = source_pixmap_priv->base.pixmap; - if (source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE - && (source->transform - || source->repeatType != RepeatNone)) - return FALSE; - } - if (mask_pixmap_priv) { + if (mask_pixmap_priv) mask_pixmap = mask_pixmap_priv->base.pixmap; - if (mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE - && (mask->transform - || mask->repeatType != RepeatNone)) - return FALSE; - } if (source->repeat) source_repeat_type = source->repeatType; @@ -477,10 +971,68 @@ glamor_composite_largepixmap_region(CARD8 op, glamor_priv = dest_pixmap_priv->base.glamor_priv; fixed_block_width = glamor_priv->max_fbo_size; fixed_block_height = glamor_priv->max_fbo_size; + /* If we got an totally out-of-box region for a source or mask + * region without repeat, we need to set it as null_source and + * give it a solid color (0,0,0,0). */ + null_source = 0; + null_mask = 0; RegionTranslate(region, -dest->pDrawable->x, -dest->pDrawable->y); - if (force_clip) + /* need to transform the dest region to the correct sourcei/mask region. + * it's a little complex, as one single edge of the + * target region may be transformed to cross a block boundary of the + * source or mask. Then it's impossible to handle it as usual way. + * We may have to split the original dest region to smaller region, and + * make sure each region's transformed region can fit into one texture, + * and then continue this loop again, and each time when a transformed region + * cross the bound, we need to copy it to a single pixmap and do the composition + * with the new pixmap. If the transformed region doesn't cross a source/mask's + * boundary then we don't need to copy. + * + */ + if (source_pixmap_priv + && source->transform + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + int source_transformed_block_width, source_transformed_block_height; + if (!glamor_get_transform_block_size(source->transform, + source_pixmap_priv->large.block_w, + source_pixmap_priv->large.block_h, + &source_transformed_block_width, + &source_transformed_block_height)) { + DEBUGF("source block size less than 1, fallback.\n"); + RegionTranslate(region, dest->pDrawable->x, + dest->pDrawable->y); + return FALSE; + } + fixed_block_width = min(fixed_block_width , source_transformed_block_width); + fixed_block_height = min(fixed_block_height , source_transformed_block_height); + DEBUGF("new source block size %d x %d \n", fixed_block_width, fixed_block_height); + } + + if (mask_pixmap_priv + && mask->transform + && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + int mask_transformed_block_width, mask_transformed_block_height; + if (!glamor_get_transform_block_size(mask->transform, + mask_pixmap_priv->large.block_w, + mask_pixmap_priv->large.block_h, + &mask_transformed_block_width, + &mask_transformed_block_height)) { + DEBUGF("mask block size less than 1, fallback.\n"); + RegionTranslate(region, dest->pDrawable->x, + dest->pDrawable->y); + return FALSE; + } + fixed_block_width = min(fixed_block_width , mask_transformed_block_width); + fixed_block_height = min(fixed_block_height , mask_transformed_block_height); + DEBUGF("new mask block size %d x %d \n", fixed_block_width, fixed_block_height); + } + + /*compute the correct block width and height whose transformed source/mask + *region can fit into one texture.*/ + if (force_clip || fixed_block_width < glamor_priv->max_fbo_size + || fixed_block_height < glamor_priv->max_fbo_size) clipped_dest_regions = glamor_compute_clipped_regions_ext(dest_pixmap_priv, region, &n_dest_regions, @@ -492,93 +1044,238 @@ glamor_composite_largepixmap_region(CARD8 op, &n_dest_regions, 0); DEBUGF("dest clipped result %d region: \n", n_dest_regions); + if (source_pixmap_priv == dest_pixmap_priv + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + /* XXX self-copy...*/ + need_free_source_pixmap_priv = source_pixmap_priv; + source_pixmap_priv = malloc(sizeof(*source_pixmap_priv)); + *source_pixmap_priv = *need_free_source_pixmap_priv; + need_free_source_pixmap_priv = source_pixmap_priv; + } for(i = 0; i < n_dest_regions; i++) { DEBUGF("dest region %d idx %d\n", i, clipped_dest_regions[i].block_idx); DEBUGRegionPrint(clipped_dest_regions[i].region); SET_PIXMAP_FBO_CURRENT(dest_pixmap_priv, clipped_dest_regions[i].block_idx); if ( source_pixmap_priv && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (!source->transform && source_repeat_type != RepeatPad) { RegionTranslate(clipped_dest_regions[i].region, x_source - x_dest, y_source - y_dest); clipped_source_regions = glamor_compute_clipped_regions(source_pixmap_priv, clipped_dest_regions[i].region, &n_source_regions, source_repeat_type); + is_normal_source_fbo = 1; + } + else { + clipped_source_regions = glamor_compute_transform_clipped_regions(source_pixmap_priv, + source->transform, + clipped_dest_regions[i].region, + &n_source_regions, + x_source - x_dest, y_source - y_dest, + source_repeat_type); + is_normal_source_fbo = 0; + if (n_source_regions == 0) { + /* Pad the out-of-box region to (0,0,0,0). */ + null_source = 1; + n_source_regions = 1; + } else + _glamor_process_transformed_clipped_region(source_pixmap_priv, + source_repeat_type, clipped_source_regions, &n_source_regions, + &need_clean_source_fbo); + } DEBUGF("source clipped result %d region: \n", n_source_regions); for(j = 0; j < n_source_regions; j++) { - SET_PIXMAP_FBO_CURRENT(source_pixmap_priv, - clipped_source_regions[j].block_idx); + if (is_normal_source_fbo) + SET_PIXMAP_FBO_CURRENT(source_pixmap_priv, + clipped_source_regions[j].block_idx); if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - DEBUGF("source region %d idx %d\n", j, clipped_source_regions[j].block_idx); - DEBUGRegionPrint(clipped_source_regions[j].region); - RegionTranslate(clipped_source_regions[j].region, - - x_source + x_mask, + if (is_normal_mask_fbo && is_normal_source_fbo) { + /* both mask and source are normal fbo box without transform or repeatpad. + * The region is clipped against source and then we clip it against mask here.*/ + DEBUGF("source region %d idx %d\n", j, clipped_source_regions[j].block_idx); + DEBUGRegionPrint(clipped_source_regions[j].region); + RegionTranslate(clipped_source_regions[j].region, + - x_source + x_mask, - y_source + y_mask); - clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, - clipped_source_regions[j].region, - &n_mask_regions, mask_repeat_type); + clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, + clipped_source_regions[j].region, + &n_mask_regions, mask_repeat_type); + is_normal_mask_fbo = 1; + } else if (is_normal_mask_fbo && !is_normal_source_fbo) { + assert(n_source_regions == 1); + /* The source fbo is not a normal fbo box, it has transform or repeatpad. + * the valid clip region should be the clip dest region rather than the + * clip source region.*/ + RegionTranslate(clipped_dest_regions[i].region, + - x_dest + x_mask, + - y_dest + y_mask); + clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, + clipped_dest_regions[i].region, + &n_mask_regions, mask_repeat_type); + is_normal_mask_fbo = 1; + } else { + /* This mask region has transform or repeatpad, we need clip it agains the previous + * valid region rather than the mask region. */ + if (!is_normal_source_fbo) + clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, + mask->transform, + clipped_dest_regions[i].region, + &n_mask_regions, + x_mask - x_dest, + y_mask - y_dest, + mask_repeat_type); + else + clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, + mask->transform, + clipped_source_regions[j].region, + &n_mask_regions, + x_mask - x_source, y_mask - y_source, + mask_repeat_type); + is_normal_mask_fbo = 0; + if (n_mask_regions == 0) { + /* Pad the out-of-box region to (0,0,0,0). */ + null_mask = 1; + n_mask_regions = 1; + } else + _glamor_process_transformed_clipped_region(mask_pixmap_priv, + mask_repeat_type, clipped_mask_regions, &n_mask_regions, + &need_clean_mask_fbo); + } DEBUGF("mask clipped result %d region: \n", n_mask_regions); #define COMPOSITE_REGION(region) do { \ if (!glamor_composite_clipped_region(op, \ - source, \ - mask, dest, region, \ + null_source ? NULL : source, \ + null_mask ? NULL : mask, dest, region, \ x_source, y_source, x_mask, y_mask, \ x_dest, y_dest)) { \ assert(0); \ } \ } while(0) + for(k = 0; k < n_mask_regions; k++) { DEBUGF("mask region %d idx %d\n", k, clipped_mask_regions[k].block_idx); DEBUGRegionPrint(clipped_mask_regions[k].region); - SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, - clipped_mask_regions[k].block_idx); - DEBUGF("mask fbo off %d %d \n", - mask_pixmap_priv->large.box.x1, - mask_pixmap_priv->large.box.y1); - DEBUGF("start composite mask hasn't transform.\n"); - RegionTranslate(clipped_mask_regions[k].region, - x_dest - x_mask + dest->pDrawable->x, - y_dest - y_mask + dest->pDrawable->y); - COMPOSITE_REGION(clipped_mask_regions[k].region); + if (is_normal_mask_fbo) { + SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, + clipped_mask_regions[k].block_idx); + DEBUGF("mask fbo off %d %d \n", + mask_pixmap_priv->large.box.x1, + mask_pixmap_priv->large.box.y1); + DEBUGF("start composite mask hasn't transform.\n"); + RegionTranslate(clipped_mask_regions[k].region, + x_dest - x_mask + dest->pDrawable->x, + y_dest - y_mask + dest->pDrawable->y); + COMPOSITE_REGION(clipped_mask_regions[k].region); + } else if (!is_normal_mask_fbo && !is_normal_source_fbo) { + DEBUGF("start composite both mask and source have transform.\n"); + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, + dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } else { + DEBUGF("start composite only mask has transform.\n"); + RegionTranslate(clipped_source_regions[j].region, + x_dest - x_source + dest->pDrawable->x, + y_dest - y_source + dest->pDrawable->y); + COMPOSITE_REGION(clipped_source_regions[j].region); + } RegionDestroy(clipped_mask_regions[k].region); } free(clipped_mask_regions); + if (null_mask) null_mask = 0; + if (need_clean_mask_fbo) { + assert(is_normal_mask_fbo == 0); + glamor_destroy_fbo(mask_pixmap_priv->base.fbo); + mask_pixmap_priv->base.fbo = NULL; + need_clean_mask_fbo = 0; + } } else { - RegionTranslate(clipped_source_regions[j].region, - -x_source + x_dest + dest->pDrawable->x, - -y_source + y_dest + dest->pDrawable->y); - COMPOSITE_REGION(clipped_source_regions[j].region); + if (is_normal_source_fbo) { + RegionTranslate(clipped_source_regions[j].region, + -x_source + x_dest + dest->pDrawable->x, + -y_source + y_dest + dest->pDrawable->y); + COMPOSITE_REGION(clipped_source_regions[j].region); + } else { + /* Source has transform or repeatPad. dest regions is the right + * region to do the composite. */ + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, + dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } } if (clipped_source_regions && clipped_source_regions[j].region) RegionDestroy(clipped_source_regions[j].region); } free(clipped_source_regions); + if (null_source) null_source = 0; + if (need_clean_source_fbo) { + assert(is_normal_source_fbo == 0); + glamor_destroy_fbo(source_pixmap_priv->base.fbo); + source_pixmap_priv->base.fbo = NULL; + need_clean_source_fbo = 0; + } } else { if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - RegionTranslate(clipped_dest_regions[i].region, - x_mask - x_dest, - y_mask - y_dest); - clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, - clipped_dest_regions[i].region, - &n_mask_regions, mask_repeat_type); + if (!mask->transform && mask_repeat_type != RepeatPad) { + RegionTranslate(clipped_dest_regions[i].region, + x_mask - x_dest, + y_mask - y_dest); + clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, + clipped_dest_regions[i].region, + &n_mask_regions, mask_repeat_type); + is_normal_mask_fbo = 1; + } + else { + clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, + mask->transform, + clipped_dest_regions[i].region, + &n_mask_regions, + x_mask - x_dest, y_mask - y_dest, + mask_repeat_type); + is_normal_mask_fbo = 0; + if (n_mask_regions == 0) { + /* Pad the out-of-box region to (0,0,0,0). */ + null_mask = 1; + n_mask_regions = 1; + } else + _glamor_process_transformed_clipped_region(mask_pixmap_priv, + mask_repeat_type, clipped_mask_regions, &n_mask_regions, + &need_clean_mask_fbo); + } + for(k = 0; k < n_mask_regions; k++) { DEBUGF("mask region %d idx %d\n", k, clipped_mask_regions[k].block_idx); DEBUGRegionPrint(clipped_mask_regions[k].region); - SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, - clipped_mask_regions[k].block_idx); - RegionTranslate(clipped_mask_regions[k].region, - x_dest - x_mask + dest->pDrawable->x, - y_dest - y_mask + dest->pDrawable->y); - COMPOSITE_REGION(clipped_mask_regions[k].region); + if (is_normal_mask_fbo) { + SET_PIXMAP_FBO_CURRENT(mask_pixmap_priv, + clipped_mask_regions[k].block_idx); + RegionTranslate(clipped_mask_regions[k].region, + x_dest - x_mask + dest->pDrawable->x, + y_dest - y_mask + dest->pDrawable->y); + COMPOSITE_REGION(clipped_mask_regions[k].region); + } else { + RegionTranslate(clipped_dest_regions[i].region, + dest->pDrawable->x, + dest->pDrawable->y); + COMPOSITE_REGION(clipped_dest_regions[i].region); + } RegionDestroy(clipped_mask_regions[k].region); } free(clipped_mask_regions); + if (null_mask) null_mask = 0; + if (need_clean_mask_fbo) { + glamor_destroy_fbo(mask_pixmap_priv->base.fbo); + mask_pixmap_priv->base.fbo = NULL; + need_clean_mask_fbo = 0; + } } else { RegionTranslate(clipped_dest_regions[i].region, @@ -590,6 +1287,8 @@ glamor_composite_largepixmap_region(CARD8 op, RegionDestroy(clipped_dest_regions[i].region); } free(clipped_dest_regions); + free(need_free_source_pixmap_priv); + free(need_free_mask_pixmap_priv); ok = TRUE; return ok; } diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b19d66c6f..40a879489 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -955,7 +955,12 @@ glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, yInverted, texcoords); else if (matrix && repeat_type != RepeatNone) - assert(0); + glamor_set_repeat_transformed_normalize_tcoords(priv, repeat_type, + matrix, xscale, yscale, + x1, y1, + x2, y2, + yInverted, + texcoords); } static Bool @@ -1718,9 +1723,9 @@ _glamor_composite(CARD8 op, extent->x2 - extent->x1, extent->y2 - extent->y1) && (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) && ((source_pixmap_priv - && source_pixmap_priv->type == GLAMOR_MEMORY) + && (source_pixmap_priv->type == GLAMOR_MEMORY || source->repeatType == RepeatPad)) || (mask_pixmap_priv - && mask_pixmap_priv->type == GLAMOR_MEMORY) + && (mask_pixmap_priv->type == GLAMOR_MEMORY || mask->repeatType == RepeatPad)) || (!source_pixmap_priv && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (!mask_pixmap_priv && mask @@ -1742,7 +1747,6 @@ _glamor_composite(CARD8 op, x_mask, y_mask, x_dest, y_dest, width, height); - else ok = glamor_composite_clipped_region(op, source, mask, dest, ®ion, diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 44c8175ae..18f7f3b10 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -39,13 +39,13 @@ #define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_)) #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) -#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ - do { \ - int w,h; \ - PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \ - *(_pxscale_) = 1.0 / w; \ - *(_pyscale_) = 1.0 / h; \ - } while(0) +#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_)\ + do { \ + int w,h; \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \ + *(_pxscale_) = 1.0 / w; \ + *(_pyscale_) = 1.0 / h; \ + } while(0) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ @@ -108,24 +108,175 @@ } \ } while(0) +#define fmod(x, w) (x - w * floor((float)x/w)) + +#define fmodulus(x, w, c) do {c = fmod(x, w); \ + c = c >= 0 ? c : c + w;} \ + while(0) +/* @x: is current coord + * @x2: is the right/bottom edge + * @w: is current width or height + * @odd: is output value, 0 means we are in an even region, 1 means we are in a + * odd region. + * @c: is output value, equal to x mod w. */ +#define fodd_repeat_mod(x, x2, w, odd, c) \ + do { \ + float shift; \ + fmodulus((x), w, c); \ + shift = fabs((x) - (c)); \ + shift = floor(fabs(round(shift)) / w); \ + odd = (int)shift & 1; \ + if (odd && (((x2 % w) == 0) && \ + round(fabs(x)) == x2)) \ + odd = 0; \ + } while(0) + +/* @txy: output value, is the corrected coords. + * @xy: input coords to be fixed up. + * @cd: xy mod wh, is a input value. + * @wh: current width or height. + * @bxy1,bxy2: current box edge's x1/x2 or y1/y2 + * + * case 1: + * ---------- + * | * | + * | | + * ---------- + * tx = (c - x1) mod w + * + * case 2: + * --------- + * * | | + * | | + * --------- + * tx = - (c - (x1 mod w)) + * + * case 3: + * + * ---------- + * | | * + * | | + * ---------- + * tx = ((x2 mod x) - c) + (x2 - x1) + **/ +#define __glamor_repeat_reflect_fixup(txy, xy, \ + cd, wh, bxy1, bxy2) \ + do { \ + cd = wh - cd; \ + if ( xy >= bxy1 && xy < bxy2) { \ + cd = cd - bxy1; \ + fmodulus(cd, wh, txy); \ + } else if (xy < bxy1) { \ + float bxy1_mod; \ + fmodulus(bxy1, wh, bxy1_mod); \ + txy = -(cd - bxy1_mod); \ + } \ + else if (xy >= bxy2) { \ + float bxy2_mod; \ + fmodulus(bxy2, wh, bxy2_mod); \ + if (bxy2_mod == 0) \ + bxy2_mod = wh; \ + txy = (bxy2_mod - cd) + bxy2 - bxy1; \ + } else {assert(0); txy = 0;} \ + } while(0) + +#define _glamor_repeat_reflect_fixup(txy, xy, cd, odd, \ + wh, bxy1, bxy2) \ + do { \ + if (odd) { \ + __glamor_repeat_reflect_fixup(txy, xy, \ + cd, wh, bxy1, bxy2); \ + } else \ + txy = xy - bxy1; \ + } while(0) + +#define _glamor_get_reflect_transform_coords(priv, repeat_type, \ + tx1, ty1, \ + _x1_, _y1_) \ + do { \ + int odd_x, odd_y; \ + float c, d; \ + fodd_repeat_mod(_x1_,priv->box.x2, \ + priv->base.pixmap->drawable.width, \ + odd_x, c); \ + fodd_repeat_mod(_y1_, priv->box.y2, \ + priv->base.pixmap->drawable.height, \ + odd_y, d); \ + DEBUGF("c %f d %f oddx %d oddy %d \n", \ + c, d, odd_x, odd_y); \ + DEBUGF("x2 %d x1 %d fbo->width %d \n", priv->box.x2, \ + priv->box.x1, priv->base.fbo->width); \ + DEBUGF("y2 %d y1 %d fbo->height %d \n", priv->box.y2, \ + priv->box.y1, priv->base.fbo->height); \ + _glamor_repeat_reflect_fixup(tx1, _x1_, c, odd_x, \ + priv->base.pixmap->drawable.width, \ + priv->box.x1, priv->box.x2); \ + _glamor_repeat_reflect_fixup(ty1, _y1_, d, odd_y, \ + priv->base.pixmap->drawable.height, \ + priv->box.y1, priv->box.y2); \ + } while(0) + #define _glamor_get_repeat_coords(priv, repeat_type, tx1, \ ty1, tx2, ty2, \ _x1_, _y1_, _x2_, \ _y2_, c, d, odd_x, odd_y) \ do { \ if (repeat_type == RepeatReflect) { \ - assert(0); \ + DEBUGF("x1 y1 %d %d\n", \ + _x1_, _y1_ ); \ + DEBUGF("width %d box.x1 %d \n", \ + (priv)->base.pixmap->drawable.width, \ + priv->box.x1); \ + if (odd_x) { \ + c = (priv)->base.pixmap->drawable.width \ + - c; \ + tx1 = c - priv->box.x1; \ + tx2 = tx1 - ((_x2_) - (_x1_)); \ + } else { \ + tx1 = c - priv->box.x1; \ + tx2 = tx1 + ((_x2_) - (_x1_)); \ + } \ + if (odd_y){ \ + d = (priv)->base.pixmap->drawable.height\ + - d; \ + ty1 = d - priv->box.y1; \ + ty2 = ty1 - ((_y2_) - (_y1_)); \ + } else { \ + ty1 = d - priv->box.y1; \ + ty2 = ty1 + ((_y2_) - (_y1_)); \ + } \ } else if (repeat_type == RepeatNormal) { \ tx1 = (c - priv->box.x1); \ ty1 = (d - priv->box.y1); \ tx2 = tx1 + ((_x2_) - (_x1_)); \ ty2 = ty1 + ((_y2_) - (_y1_)); \ } else { \ - assert(0); \ + tx1 = _x1_ - priv->box.x1; \ + ty1 = _y1_ - priv->box.y1; \ + tx2 = tx1 + ((_x2_) - (_x1_)); \ + ty2 = ty1 + ((_y2_) - (_y1_)); \ } \ } while(0) +/* _x1_ ... _y2_ may has fractional. */ +#define glamor_get_repeat_transform_coords(priv, repeat_type, tx1, \ + ty1, _x1_, _y1_) \ + do { \ + DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \ + (priv)->base.pixmap->drawable.width, \ + priv->box.x1, priv->box.x2, priv->box.y1, \ + priv->box.y2); \ + DEBUGF("x1 %f y1 %f \n", _x1_, _y1_); \ + if (repeat_type != RepeatReflect) { \ + tx1 = _x1_ - priv->box.x1; \ + ty1 = _y1_ - priv->box.y1; \ + } else \ + _glamor_get_reflect_transform_coords(priv, repeat_type, \ + tx1, ty1, \ + _x1_, _y1_); \ + DEBUGF("tx1 %f ty1 %f \n", tx1, ty1); \ + } while(0) /* _x1_ ... _y2_ must be integer. */ #define glamor_get_repeat_coords(priv, repeat_type, tx1, \ @@ -152,8 +303,6 @@ odd_x, odd_y); \ } while(0) - - #define glamor_transform_point(matrix, tx, ty, x, y) \ do { \ int i; \ @@ -221,6 +370,58 @@ yInverted); \ } while (0) +#define glamor_set_repeat_transformed_normalize_tcoords( priv, \ + repeat_type, \ + matrix, \ + xscale, \ + yscale, \ + _x1_, _y1_, \ + _x2_, _y2_, \ + yInverted, \ + texcoords) \ + do { \ + if (priv->type != GLAMOR_TEXTURE_LARGE) { \ + glamor_set_transformed_normalize_tcoords(priv, matrix, xscale, \ + yscale, _x1_, _y1_, \ + _x2_, _y2_, yInverted, \ + texcoords); \ + } else { \ + /* For a large pixmap, if both transform and repeat are set, + * the transform must only has x and y scale factor.*/ \ + float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; \ + float ttx1, tty1, ttx2, tty2, ttx3, tty3, ttx4, tty4; \ + DEBUGF("original coords %d %d %d %d\n", _x1_, _y1_, _x2_, _y2_); \ + glamor_transform_point(matrix, tx1, ty1, _x1_, _y1_); \ + glamor_transform_point(matrix, tx2, ty2, _x2_, _y1_); \ + glamor_transform_point(matrix, tx3, ty3, _x2_, _y2_); \ + glamor_transform_point(matrix, tx4, ty4, _x1_, _y2_); \ + DEBUGF("transformed %f %f %f %f %f %f %f %f\n", \ + tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4); \ + glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + ttx1, tty1, \ + tx1, ty1); \ + glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + ttx2, tty2, \ + tx2, ty2); \ + glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + ttx3, tty3, \ + tx3, ty3); \ + glamor_get_repeat_transform_coords((&priv->large), repeat_type, \ + ttx4, tty4, \ + tx4, ty4); \ + DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, \ + ttx2, tty2, ttx3, tty3, ttx4, tty4); \ + _glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1, \ + texcoords, yInverted); \ + _glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2, \ + texcoords + 2, yInverted); \ + _glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3, \ + texcoords + 4, yInverted); \ + _glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4, \ + texcoords + 6, yInverted); \ + } \ + } while (0) + #define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \ ty1, tx2, ty2, \ yInverted, vertices) \ @@ -261,6 +462,8 @@ tx2, ty2, yInverted, vertices); \ } while(0) + + #define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \ xscale, yscale, \ _x1_, _y1_, _x2_, _y2_, \ @@ -480,7 +683,7 @@ format_for_pixmap(PixmapPtr pixmap) /* * Map picture's format to the correct gl texture format and type. - * no_alpha is used to indicate whehter we need to wire alpha to 1. + * no_alpha is used to indicate whehter we need to wire alpha to 1. * * Although opengl support A1/GL_BITMAP, we still don't use it * here, it seems that mesa has bugs when uploading a A1 bitmap. @@ -899,7 +1102,7 @@ inline static Bool glamor_ddx_fallback_check_pixmap(DrawablePtr drawable) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - return (!pixmap_priv + return (!pixmap_priv || (pixmap_priv->type == GLAMOR_TEXTURE_DRM || pixmap_priv->type == GLAMOR_MEMORY || pixmap_priv->type == GLAMOR_DRM_ONLY)); From 5325c800f706f46085735d608f57d513da63cddf Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 11:42:46 +0800 Subject: [PATCH 386/462] largepixmap: Support self composite for large pixmap. The simplest way to support large pixmap's self compositing is to just clone a pixmap private data structure, and change the fbo and box to point to the correct postions. Don't need to copy a new box. Signed-off-by: Zhigang Gong --- glamor/glamor_largepixmap.c | 21 ++++++---- glamor/glamor_priv.h | 3 ++ glamor/glamor_render.c | 78 +++++++++++++++++++------------------ 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c index 31af71150..80cd6ad23 100644 --- a/glamor/glamor_largepixmap.c +++ b/glamor/glamor_largepixmap.c @@ -22,8 +22,7 @@ __glamor_compute_clipped_regions(int block_w, int x, int y, int w, int h, RegionPtr region, - int *n_region, - int repeat) + int *n_region) { glamor_pixmap_clipped_regions * clipped_regions; BoxPtr extent; @@ -157,7 +156,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, 0, 0, priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.height, - region, n_region, 0 + region, n_region ); if (clipped_regions == NULL) { @@ -185,7 +184,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, width, height, clipped_regions[i].region, - &inner_n_regions, 0); + &inner_n_regions); for(j = 0; j < inner_n_regions; j++) { result_regions[k].region = inner_regions[j].region; @@ -339,7 +338,7 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, 0, 0, priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.height, - region, n_region, 0 + region, n_region ); if (saved_region) RegionDestroy(region); @@ -1044,14 +1043,17 @@ glamor_composite_largepixmap_region(CARD8 op, &n_dest_regions, 0); DEBUGF("dest clipped result %d region: \n", n_dest_regions); - if (source_pixmap_priv == dest_pixmap_priv - && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (source_pixmap_priv + && (source_pixmap_priv == dest_pixmap_priv || source_pixmap_priv == mask_pixmap_priv) + && source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { /* XXX self-copy...*/ need_free_source_pixmap_priv = source_pixmap_priv; source_pixmap_priv = malloc(sizeof(*source_pixmap_priv)); *source_pixmap_priv = *need_free_source_pixmap_priv; need_free_source_pixmap_priv = source_pixmap_priv; } + assert(mask_pixmap_priv != dest_pixmap_priv); + for(i = 0; i < n_dest_regions; i++) { DEBUGF("dest region %d idx %d\n", i, clipped_dest_regions[i].block_idx); @@ -1149,7 +1151,10 @@ glamor_composite_largepixmap_region(CARD8 op, #define COMPOSITE_REGION(region) do { \ if (!glamor_composite_clipped_region(op, \ null_source ? NULL : source, \ - null_mask ? NULL : mask, dest, region, \ + null_mask ? NULL : mask, dest, \ + null_source ? NULL : source_pixmap_priv, \ + null_mask ? NULL : mask_pixmap_priv, \ + dest_pixmap_priv, region, \ x_source, y_source, x_mask, y_mask, \ x_dest, y_dest)) { \ assert(0); \ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index d9f643837..c15f189c3 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -667,6 +667,9 @@ glamor_composite_clipped_region(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, + glamor_pixmap_private *soruce_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, RegionPtr region, int x_source, int y_source, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 40a879489..e5210cf82 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -968,22 +968,19 @@ glamor_composite_with_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, int nrect, glamor_composite_rect_t * rects) { ScreenPtr screen = dest->pDrawable->pScreen; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; glamor_gl_dispatch *dispatch; - PixmapPtr dest_pixmap = - glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; 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; GLfloat dst_xscale, dst_yscale; - GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = - 1, src_yscale = 1; + GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; struct shader_key key; glamor_composite_shader *shader; float vertices[8], source_texcoords[8], mask_texcoords[8]; @@ -1000,7 +997,6 @@ glamor_composite_with_shader(CARD8 op, int nrect_max; Bool ret = FALSE; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("dest has no fbo.\n"); goto fail; @@ -1075,10 +1071,7 @@ glamor_composite_with_shader(CARD8 op, } 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); + source_pixmap = source_pixmap_priv->base.pixmap; if (source_pixmap == dest_pixmap) { /* XXX source and the dest share the same texture. * Does it need special handle? */ @@ -1099,8 +1092,7 @@ glamor_composite_with_shader(CARD8 op, } 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); + mask_pixmap = mask_pixmap_priv->base.pixmap; if (mask_pixmap == dest_pixmap) { glamor_fallback("mask == dest\n"); goto fail; @@ -1432,6 +1424,9 @@ glamor_composite_clipped_region(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, RegionPtr region, int x_source, int y_source, @@ -1441,13 +1436,10 @@ glamor_composite_clipped_region(CARD8 op, int y_dest) { ScreenPtr screen = dest->pDrawable->pScreen; - glamor_pixmap_private *dest_pixmap_priv; - glamor_pixmap_private *source_pixmap_priv = - NULL, *mask_pixmap_priv = NULL; - PixmapPtr dest_pixmap = - glamor_get_drawable_pixmap(dest->pDrawable); PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; PicturePtr temp_src = source, temp_mask = mask; + glamor_pixmap_private *temp_src_priv = source_pixmap_priv; + glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; BoxPtr extent; @@ -1472,20 +1464,12 @@ glamor_composite_clipped_region(CARD8 op, y_temp_mask = y_mask; DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); - DEBUGF("dest pixmap %p ", dest_pixmap); - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - /* Currently. Always fallback to cpu if destination is in CPU memory. */ + if (source_pixmap_priv) + source_pixmap = source_pixmap_priv->base.pixmap; - if (source && source->pDrawable) { - source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - } - - if (mask && mask->pDrawable) { - mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - } + if (mask_pixmap_priv) + mask_pixmap = mask_pixmap_priv->base.pixmap; /* XXX is it possible source mask have non-zero drawable.x/y? */ if (source @@ -1504,6 +1488,7 @@ glamor_composite_clipped_region(CARD8 op, temp_src = source; goto out; } + temp_src_priv = glamor_get_pixmap_private((PixmapPtr)(temp_src->pDrawable)); x_temp_src = - extent->x1 + x_dest; y_temp_src = - extent->y1 + y_dest; } @@ -1527,6 +1512,7 @@ glamor_composite_clipped_region(CARD8 op, temp_mask = mask; goto out; } + temp_mask_priv = glamor_get_pixmap_private((PixmapPtr)(temp_mask->pDrawable)); x_temp_mask = - extent->x1 + x_dest; y_temp_mask = - extent->y1 + y_dest; } @@ -1538,6 +1524,7 @@ glamor_composite_clipped_region(CARD8 op, if (op == PictOpOver) { glamor_composite_clipped_region(PictOpOutReverse, temp_src, temp_mask, dest, + temp_src_priv, temp_mask_priv, dest_pixmap_priv, region, x_temp_src, y_temp_src, x_temp_mask, y_temp_mask, @@ -1545,6 +1532,7 @@ glamor_composite_clipped_region(CARD8 op, glamor_composite_clipped_region(PictOpAdd, temp_src, temp_mask, dest, + temp_src_priv, temp_mask_priv, dest_pixmap_priv, region, x_temp_src, y_temp_src, x_temp_mask, y_temp_mask, @@ -1598,8 +1586,10 @@ glamor_composite_clipped_region(CARD8 op, prect[i].width = box[i].x2 - box[i].x1; prect[i].height = box[i].y2 - box[i].y1; } - ok = glamor_composite_with_shader(op, temp_src, temp_mask, - dest, box_cnt, prect); + ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, + temp_src_priv, temp_mask_priv, + dest_pixmap_priv, + box_cnt, prect); if (!ok) break; nbox -= box_cnt; @@ -1749,7 +1739,11 @@ _glamor_composite(CARD8 op, width, height); else ok = glamor_composite_clipped_region(op, source, - mask, dest, ®ion, + mask, dest, + source_pixmap_priv, + mask_pixmap_priv, + dest_pixmap_priv, + ®ion, x_source, y_source, x_mask, y_mask, x_dest, y_dest); @@ -2045,7 +2039,17 @@ glamor_composite_glyph_rects(CARD8 op, if (!(glamor_is_large_picture(src) || (mask && glamor_is_large_picture(mask)) || glamor_is_large_picture(dst))) { - if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) + glamor_pixmap_private *src_pixmap_priv = NULL; + glamor_pixmap_private *mask_pixmap_priv = NULL; + glamor_pixmap_private *dst_pixmap_priv; + + dst_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(dst->pDrawable)); + if (mask && mask->pDrawable) + mask_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(mask->pDrawable)); + if (src->pDrawable) + src_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(src->pDrawable)); + if (glamor_composite_with_shader(op, src, mask, dst, src_pixmap_priv, + mask_pixmap_priv, dst_pixmap_priv, nrect, rects)) return; } From 8ca16754f7e95e47423183bbd5f72966b937f6c8 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 13:05:48 +0800 Subject: [PATCH 387/462] largepixmap: Fix the selfcopy issue. If the source and destination are the same pixmap/fbo, and we need to split the copy to small pieces. Then we do need to consider the sequence of the small pieces when the copy area has overlaps. This commit take the reverse/upsidedown into the clipping function, thus it can generate correct sequence and avoid corruption self copying. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 19 ++++---- glamor/glamor_fill.c | 2 +- glamor/glamor_largepixmap.c | 91 ++++++++++++++++++++++++++----------- glamor/glamor_pixmap.c | 4 +- glamor/glamor_priv.h | 10 ++-- glamor/glamor_tile.c | 4 +- 6 files changed, 86 insertions(+), 44 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 4d68dbe66..bfd957af1 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -458,17 +458,18 @@ _glamor_copy_n_to_n(DrawablePtr src, int n_dst_region, i, j; PixmapPtr temp_source_pixmap; glamor_pixmap_private *temp_source_priv = NULL; - int temp_dx = 0, temp_dy = 0; RegionTranslate(®ion, dst_x_off, dst_y_off); if (!force_clip) clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, - ®ion, &n_dst_region, 0); + ®ion, &n_dst_region, 0, + reverse, upsidedown); else clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, ®ion, &n_dst_region, glamor_priv->max_fbo_size, - glamor_priv->max_fbo_size); + glamor_priv->max_fbo_size, + reverse, upsidedown); for(i = 0; i < n_dst_region; i++) { int n_src_region; @@ -484,7 +485,8 @@ _glamor_copy_n_to_n(DrawablePtr src, -dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, - &n_src_region, 0); + &n_src_region, 0, + reverse, upsidedown); DEBUGF("Source is large pixmap.\n"); for (j = 0; j < n_src_region; j++) { @@ -507,9 +509,7 @@ _glamor_copy_n_to_n(DrawablePtr src, *temp_source_priv = *src_pixmap_priv; temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx]; - /* XXX need revisit here. */ - temp_dx = dx/* - src_x_off*/; - temp_dy = dy/* - src_y_off*/; + temp_source_priv->base.pixmap = temp_source_pixmap; } assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv && (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); @@ -531,8 +531,9 @@ _glamor_copy_n_to_n(DrawablePtr src, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); else { - ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, - n_current_boxes, temp_dx, temp_dy, reverse, + ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, + dst, gc, current_boxes, + n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); temp_source_priv->type = GLAMOR_MEMORY; temp_source_priv->base.fbo = NULL; diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 5b84dd66e..e37114879 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -273,7 +273,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, box.x2 = x + width; box.y2 = y + height; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); for(i = 0; i < n_region; i++) { BoxPtr boxes; diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c index 80cd6ad23..f07095a92 100644 --- a/glamor/glamor_largepixmap.c +++ b/glamor/glamor_largepixmap.c @@ -22,14 +22,19 @@ __glamor_compute_clipped_regions(int block_w, int x, int y, int w, int h, RegionPtr region, - int *n_region) + int *n_region, + int reverse, + int upsidedown) { glamor_pixmap_clipped_regions * clipped_regions; BoxPtr extent; int start_x, start_y, end_x, end_y; int start_block_x, start_block_y; int end_block_x, end_block_y; - int i, j; + int loop_start_block_x, loop_start_block_y; + int loop_end_block_x, loop_end_block_y; + int loop_block_stride; + int i, j, delta_i, delta_j; int width, height; RegionRec temp_region; RegionPtr current_region; @@ -66,19 +71,41 @@ __glamor_compute_clipped_regions(int block_w, * (end_block_y - start_block_y + 1), sizeof(*clipped_regions)); - block_idx = (start_block_y - 1) * block_stride; DEBUGF("startx %d starty %d endx %d endy %d \n", start_x, start_y, end_x, end_y); DEBUGF("start_block_x %d end_block_x %d \n", start_block_x, end_block_x); DEBUGF("start_block_y %d end_block_y %d \n", start_block_y, end_block_y); - for(j = start_block_y; j <= end_block_y; j++) + if (!reverse) { + loop_start_block_x = start_block_x; + loop_end_block_x = end_block_x + 1; + delta_i = 1; + } else { + loop_start_block_x = end_block_x; + loop_end_block_x = start_block_x - 1; + delta_i = -1; + } + + if (!upsidedown) { + loop_start_block_y = start_block_y; + loop_end_block_y = end_block_y + 1; + delta_j = 1; + } else { + loop_start_block_y = end_block_y; + loop_end_block_y = start_block_y - 1; + delta_j = -1; + } + + loop_block_stride = delta_j * block_stride; + block_idx = (loop_start_block_y - delta_j) * block_stride; + + for(j = loop_start_block_y; j != loop_end_block_y; j += delta_j) { - block_idx += block_stride; - temp_block_idx = block_idx + start_block_x; - for(i = start_block_x; - i <= end_block_x; i++, temp_block_idx++) + block_idx += loop_block_stride; + temp_block_idx = block_idx + loop_start_block_x; + for(i = loop_start_block_x; + i != loop_end_block_x; i += delta_i, temp_block_idx += delta_i) { BoxRec temp_box; temp_box.x1 = x + i * block_w; @@ -123,7 +150,8 @@ glamor_pixmap_clipped_regions * glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, - int inner_block_w, int inner_block_h) + int inner_block_w, int inner_block_h, + int reverse, int upsidedown) { glamor_pixmap_clipped_regions * clipped_regions, *inner_regions, *result_regions; int i, j, x, y, k, inner_n_regions; @@ -156,7 +184,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, 0, 0, priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.height, - region, n_region + region, n_region, reverse, upsidedown ); if (clipped_regions == NULL) { @@ -184,7 +212,7 @@ glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, width, height, clipped_regions[i].region, - &inner_n_regions); + &inner_n_regions, reverse, upsidedown); for(j = 0; j < inner_n_regions; j++) { result_regions[k].region = inner_regions[j].region; @@ -293,7 +321,8 @@ _glamor_largepixmap_reflect_fixup(short *xy1, short *xy2, int wh) static glamor_pixmap_clipped_regions * _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, - int repeat_type, int is_transform) + int repeat_type, int is_transform, + int reverse, int upsidedown) { glamor_pixmap_clipped_regions * clipped_regions; BoxPtr extent; @@ -338,7 +367,7 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, 0, 0, priv->base.pixmap->drawable.width, priv->base.pixmap->drawable.height, - region, n_region + region, n_region, reverse, upsidedown ); if (saved_region) RegionDestroy(region); @@ -592,9 +621,11 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, } glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *n_region, int repeat_type) +glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, + int *n_region, int repeat_type, + int reverse, int upsidedown) { - return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0); + return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0, reverse, upsidedown); } /* XXX overflow still exist. maybe we need to change to use region32. @@ -602,7 +633,8 @@ glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, in **/ glamor_pixmap_clipped_regions * glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, - RegionPtr region, int *n_region, int dx, int dy, int repeat_type) + RegionPtr region, int *n_region, int dx, int dy, int repeat_type, + int reverse, int upsidedown) { BoxPtr temp_extent; struct pixman_box32 temp_box; @@ -642,7 +674,8 @@ glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pix temp_region, n_region, repeat_type, - 1); + 1, reverse, + upsidedown); DEBUGF("n_regions = %d \n", *n_region); RegionDestroy(temp_region); @@ -1036,12 +1069,13 @@ glamor_composite_largepixmap_region(CARD8 op, region, &n_dest_regions, fixed_block_width, - fixed_block_height); + fixed_block_height, + 0, 0); else clipped_dest_regions = glamor_compute_clipped_regions(dest_pixmap_priv, region, &n_dest_regions, - 0); + 0, 0, 0); DEBUGF("dest clipped result %d region: \n", n_dest_regions); if (source_pixmap_priv && (source_pixmap_priv == dest_pixmap_priv || source_pixmap_priv == mask_pixmap_priv) @@ -1066,7 +1100,8 @@ glamor_composite_largepixmap_region(CARD8 op, y_source - y_dest); clipped_source_regions = glamor_compute_clipped_regions(source_pixmap_priv, clipped_dest_regions[i].region, - &n_source_regions, source_repeat_type); + &n_source_regions, source_repeat_type, + 0, 0); is_normal_source_fbo = 1; } else { @@ -1075,7 +1110,7 @@ glamor_composite_largepixmap_region(CARD8 op, clipped_dest_regions[i].region, &n_source_regions, x_source - x_dest, y_source - y_dest, - source_repeat_type); + source_repeat_type, 0, 0); is_normal_source_fbo = 0; if (n_source_regions == 0) { /* Pad the out-of-box region to (0,0,0,0). */ @@ -1104,7 +1139,8 @@ glamor_composite_largepixmap_region(CARD8 op, - y_source + y_mask); clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_source_regions[j].region, - &n_mask_regions, mask_repeat_type); + &n_mask_regions, mask_repeat_type, + 0, 0); is_normal_mask_fbo = 1; } else if (is_normal_mask_fbo && !is_normal_source_fbo) { assert(n_source_regions == 1); @@ -1116,7 +1152,8 @@ glamor_composite_largepixmap_region(CARD8 op, - y_dest + y_mask); clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_dest_regions[i].region, - &n_mask_regions, mask_repeat_type); + &n_mask_regions, mask_repeat_type, + 0, 0); is_normal_mask_fbo = 1; } else { /* This mask region has transform or repeatpad, we need clip it agains the previous @@ -1128,14 +1165,14 @@ glamor_composite_largepixmap_region(CARD8 op, &n_mask_regions, x_mask - x_dest, y_mask - y_dest, - mask_repeat_type); + mask_repeat_type, 0, 0); else clipped_mask_regions = glamor_compute_transform_clipped_regions(mask_pixmap_priv, mask->transform, clipped_source_regions[j].region, &n_mask_regions, x_mask - x_source, y_mask - y_source, - mask_repeat_type); + mask_repeat_type, 0, 0); is_normal_mask_fbo = 0; if (n_mask_regions == 0) { /* Pad the out-of-box region to (0,0,0,0). */ @@ -1234,7 +1271,7 @@ glamor_composite_largepixmap_region(CARD8 op, y_mask - y_dest); clipped_mask_regions = glamor_compute_clipped_regions(mask_pixmap_priv, clipped_dest_regions[i].region, - &n_mask_regions, mask_repeat_type); + &n_mask_regions, mask_repeat_type, 0, 0); is_normal_mask_fbo = 1; } else { @@ -1243,7 +1280,7 @@ glamor_composite_largepixmap_region(CARD8 op, clipped_dest_regions[i].region, &n_mask_regions, x_mask - x_dest, y_mask - y_dest, - mask_repeat_type); + mask_repeat_type, 0, 0); is_normal_mask_fbo = 0; if (n_mask_regions == 0) { /* Pad the out-of-box region to (0,0,0,0). */ diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index ca38a2bc3..10d6df396 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -715,7 +715,7 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h box.x2 = x + w; box.y2 = y + h; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); for(i = 0; i < n_region; i++) { @@ -1091,7 +1091,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, box.x2 = x + w; box.y2 = y + h; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h); for(i = 0; i < n_region; i++) { diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index c15f189c3..2af17f0ca 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -798,17 +798,21 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int w, int h, glamor_access_t access); glamor_pixmap_clipped_regions * -glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *clipped_nbox, int repeat_type); +glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, + int *clipped_nbox, int repeat_type, + int reverse, int upsidedown); glamor_pixmap_clipped_regions * glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv, RegionPtr region, int *n_region, - int inner_block_w, int inner_block_h); + int inner_block_w, int inner_block_h, + int reverse, int upsidedown); glamor_pixmap_clipped_regions * glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform, - RegionPtr region, int *n_region, int dx, int dy, int repeat_type); + RegionPtr region, int *n_region, int dx, int dy, int repeat_type, + int reverse, int upsidedown); Bool glamor_composite_largepixmap_region(CARD8 op, diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 871479bd0..206485ff2 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -242,7 +242,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, box.y2 = y + height; RegionInitBoxes(®ion, &box, 1); clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, - ®ion, &n_dst_region, 0); + ®ion, &n_dst_region, 0, 0, 0); for(i = 0; i < n_dst_region; i++) { int n_src_region; @@ -258,7 +258,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, DEBUGF("tiled a large src pixmap. %dx%d \n", tile->drawable.width, tile->drawable.height); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, - &n_src_region, 1); + &n_src_region, 1, 0, 0); DEBUGF("got %d src regions %d \n", n_src_region); for (j = 0; j < n_src_region; j++) { From bf38ee407ba1038a25efa58b8475bcf084a21042 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 11 Jun 2012 14:02:59 +0800 Subject: [PATCH 388/462] Enable large pixmap by default. Signed-off-by: Zhigang Gong --- glamor/glamor_priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 2af17f0ca..a791e04dc 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -934,9 +934,9 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER #endif -#define GLAMOR_TEXTURED_LARGE_PIXMAP 0 +#define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #if 0 -#define MAX_FBO_SIZE 512 /* For test purpose only. */ +#define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif #endif /* GLAMOR_PRIV_H */ From 6dd81c5939197eb51bc31ffbc3e6f359f2aad191 Mon Sep 17 00:00:00 2001 From: RobinHe Date: Sat, 2 Jun 2012 21:52:25 +0800 Subject: [PATCH 389/462] Create the file glamor_triangles.c Create the file glamor_trapezoid.c, extract the logic relating to trapezoid from glamor_render.c to this file. Signed-off-by: Junyan He --- glamor/Makefile.am | 1 + glamor/glamor_priv.h | 11 +-- glamor/glamor_render.c | 144 ------------------------------ glamor/glamor_trapezoid.c | 182 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+), 149 deletions(-) create mode 100644 glamor/glamor_trapezoid.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 421846c62..e29f918c4 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -34,6 +34,7 @@ libglamor_la_SOURCES = \ glamor_setspans.c \ glamor_render.c \ glamor_gradient.c \ + glamor_trapezoid.c \ glamor_tile.c \ glamor_triangles.c\ glamor_addtraps.c\ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index a791e04dc..92aa3a39b 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -688,10 +688,6 @@ void glamor_composite(CARD8 op, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); -void glamor_trapezoids(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps); void glamor_init_composite_shaders(ScreenPtr screen); void glamor_fini_composite_shaders(ScreenPtr screen); void glamor_composite_glyph_rects(CARD8 op, @@ -704,6 +700,11 @@ void glamor_composite_rects (CARD8 op, int nRect, xRectangle *rects); +/* glamor_trapezoid.c */ +void glamor_trapezoids(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps); /* glamor_tile.c */ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, @@ -935,7 +936,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_GRADIENT_SHADER #endif #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 -#if 0 +#if 1 #define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e5210cf82..da9d847da 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1881,150 +1881,6 @@ glamor_composite_nf(CARD8 op, FALSE); } -/** - * Creates an appropriate picture to upload our alpha mask into (which - * we calculated in system memory) - */ -static PicturePtr -glamor_create_mask_picture(ScreenPtr screen, - PicturePtr dst, - PictFormatPtr pict_format, - CARD16 width, CARD16 height) -{ - 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; - } - - pixmap = glamor_create_pixmap(screen, 0, 0, - pict_format->depth, - GLAMOR_CREATE_PIXMAP_CPU); - if (!pixmap) - return 0; - picture = CreatePicture(0, &pixmap->drawable, pict_format, - 0, 0, serverClient, &error); - screen->DestroyPixmap(pixmap); - return picture; -} - -/** - * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid - * accumulation in system memory. - */ -static Bool -_glamor_trapezoids(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps, Bool fallback) -{ - 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; - 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 TRUE; - } - - miTrapezoidBounds(ntrap, traps, &bounds); - - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return TRUE; - - 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 = PixmapBytePad(width, mask_format->depth); - picture = glamor_create_mask_picture(screen, dst, mask_format, - width, height); - if (!picture) - return TRUE; - - image = pixman_image_create_bits(picture->format, - width, height, NULL, stride); - if (!image) { - FreePicture(picture, 0); - return TRUE; - } - - for (; ntrap; ntrap--, traps++) - pixman_rasterize_trapezoid(image, - (pixman_trapezoid_t *) traps, - -bounds.x1, -bounds.y1); - - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - - screen->ModifyPixmapHeader(pixmap, width, height, - mask_format->depth, - BitsPerPixel(mask_format->depth), - PixmapBytePad(width, - mask_format->depth), - pixman_image_get_data(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); - - pixman_image_unref(image); - - FreePicture(picture, 0); - return TRUE; -} - -void -glamor_trapezoids(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps) -{ - _glamor_trapezoids(op, src, dst, mask_format, x_src, - y_src, ntrap, traps, TRUE); -} - -Bool -glamor_trapezoids_nf(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps) -{ - return _glamor_trapezoids(op, src, dst, mask_format, x_src, - y_src, ntrap, traps, FALSE); -} - - - void glamor_composite_glyph_rects(CARD8 op, PicturePtr src, PicturePtr mask, PicturePtr dst, diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c new file mode 100644 index 000000000..08ee2d67f --- /dev/null +++ b/glamor/glamor_trapezoid.c @@ -0,0 +1,182 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Junyan He + * + */ + +/** @file glamor_trapezoid.c + * + * Trapezoid acceleration implementation + */ + +#include "glamor_priv.h" + +#ifdef RENDER +#include "mipict.h" +#include "fbpict.h" + +/** + * Creates an appropriate picture to upload our alpha mask into (which + * we calculated in system memory) + */ +static PicturePtr +glamor_create_mask_picture(ScreenPtr screen, + PicturePtr dst, + PictFormatPtr pict_format, + CARD16 width, CARD16 height) +{ + 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; + } + + pixmap = glamor_create_pixmap(screen, 0, 0, + pict_format->depth, + GLAMOR_CREATE_PIXMAP_CPU); + if (!pixmap) + return 0; + picture = CreatePicture(0, &pixmap->drawable, pict_format, + 0, 0, serverClient, &error); + screen->DestroyPixmap(pixmap); + return picture; +} + +/** + * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid + * accumulation in system memory. + */ +static Bool +_glamor_trapezoids(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps, Bool fallback) +{ + 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; + 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 TRUE; + } + + miTrapezoidBounds(ntrap, traps, &bounds); + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return TRUE; + + 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 = PixmapBytePad(width, mask_format->depth); + picture = glamor_create_mask_picture(screen, dst, mask_format, + width, height); + if (!picture) + return TRUE; + + image = pixman_image_create_bits(picture->format, + width, height, NULL, stride); + if (!image) { + FreePicture(picture, 0); + return TRUE; + } + + for (; ntrap; ntrap--, traps++) + pixman_rasterize_trapezoid(image, + (pixman_trapezoid_t *) traps, + -bounds.x1, -bounds.y1); + + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + + screen->ModifyPixmapHeader(pixmap, width, height, + mask_format->depth, + BitsPerPixel(mask_format->depth), + PixmapBytePad(width, + mask_format->depth), + pixman_image_get_data(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); + + pixman_image_unref(image); + + FreePicture(picture, 0); + return TRUE; +} + +void +glamor_trapezoids(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) +{ + _glamor_trapezoids(op, src, dst, mask_format, x_src, + y_src, ntrap, traps, TRUE); +} + +Bool +glamor_trapezoids_nf(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) +{ + return _glamor_trapezoids(op, src, dst, mask_format, x_src, + y_src, ntrap, traps, FALSE); +} + +#endif /* RENDER */ + From bd180be619c2ef469ca40cf95023340c59960540 Mon Sep 17 00:00:00 2001 From: RobinHe Date: Sat, 2 Jun 2012 22:00:09 +0800 Subject: [PATCH 390/462] Use shader to generate the temp trapezoid mask The old manner of trapezoid render uses pixman to generate a mask pixmap and upload it to the GPU. This effect the performance. We now use shader to generate the temp trapezoid mask to avoid the uploading of this pixmap. We implement a anti-alias manner in the shader according to pixman, which will caculate the area inside the trapezoid dividing total area for every pixel and assign it to the alpha value of that pixel. The pixman use a int-to-fix manner to approximate but the shader use float, so the result may have some difference. Because the array in the shader has optimization problem, we need to emit the vertex of every trapezoid every time, which will effect the performance a lot. Need to improve it. Signed-off-by: Junyan He --- glamor/glamor.c | 6 + glamor/glamor_priv.h | 6 + glamor/glamor_trapezoid.c | 698 +++++++++++++++++++++++++++++++++++--- 3 files changed, 660 insertions(+), 50 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 74b22d39b..e4917836d 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -407,6 +407,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_pixmap_fbo(screen); glamor_init_solid_shader(screen); glamor_init_tile_shader(screen); +#ifdef GLAMOR_TRAPEZOID_SHADER + glamor_init_trapezoid_shader(screen); +#endif glamor_init_putimage_shaders(screen); glamor_init_finish_access_shaders(screen); #ifdef GLAMOR_GRADIENT_SHADER @@ -437,6 +440,9 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_fini_pixmap_fbo(screen); glamor_fini_solid_shader(screen); glamor_fini_tile_shader(screen); +#ifdef GLAMOR_TRAPEZOID_SHADER + glamor_fini_trapezoid_shader(screen); +#endif glamor_fini_putimage_shaders(screen); glamor_fini_finish_access_shaders(screen); #ifdef GLAMOR_GRADIENT_SHADER diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 92aa3a39b..b842d9b39 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -247,6 +247,9 @@ typedef struct glamor_screen_private { GLint radial_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3]; int radial_max_nstops; + /* glamor trapezoid shader. */ + GLint trapezoid_prog; + /* glamor_putimage */ GLint put_image_xybitmap_prog; GLint put_image_xybitmap_fg_uniform_location; @@ -699,6 +702,8 @@ void glamor_composite_rects (CARD8 op, xRenderColor *color, int nRect, xRectangle *rects); +void glamor_init_trapezoid_shader(ScreenPtr screen); +void glamor_fini_trapezoid_shader(ScreenPtr screen); /* glamor_trapezoid.c */ void glamor_trapezoids(CARD8 op, @@ -934,6 +939,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER +//#define GLAMOR_TRAPEZOID_SHADER #endif #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #if 1 diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 08ee2d67f..d9682baa8 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -36,15 +36,576 @@ #include "mipict.h" #include "fbpict.h" +#ifdef GLAMOR_TRAPEZOID_SHADER +void +glamor_init_trapezoid_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + GLint fs_prog, vs_prog; + + const char *trapezoid_vs = + GLAMOR_DEFAULT_PRECISION + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord;\n" + "varying vec2 source_texture;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord.xy;\n" + "}\n"; + + /* + * Because some GL fill function do not support the MultSample + * anti-alias, we need to do the MSAA here. This manner like + * pixman, will caculate the value of area in trapezoid dividing + * the totol area for each pixel, as follow: + | + ----+------------------------------------------------------> + | + | ------------- + | / \ + | / \ + | / \ + | / +----------------+ + | / |.....\ | + | / |......\ | + | / |.......\ | + | / |........\ | + | /-------------------+---------\ | + | | | + | | | + | +----------------+ + | + \|/ + + */ + const char *trapezoid_fs = + GLAMOR_DEFAULT_PRECISION + "varying vec2 source_texture; \n" + "uniform float x_per_pix; \n" + "uniform float y_per_pix; \n" + "uniform float trap_top; \n" + "uniform float trap_bottom; \n" + "uniform float trap_left_x; \n" + "uniform float trap_left_y; \n" + "uniform float trap_left_slope; \n" + "uniform int trap_left_vertical; \n" + "uniform float trap_right_x; \n" + "uniform float trap_right_y; \n" + "uniform float trap_right_slope; \n" + "uniform int trap_right_vertical; \n" + "\n" + "float get_alpha_val() \n" + "{ \n" + " float x_up_cut_left; \n" + " float x_bottom_cut_left; \n" + " float x_up_cut_right; \n" + " float x_bottom_cut_right; \n" + " \n" + " if(trap_left_vertical == 1) { \n" + " x_up_cut_left = trap_left_x; \n" + " x_bottom_cut_left = trap_left_x; \n" + " } else { \n" + " x_up_cut_left = trap_left_x \n" + " + (source_texture.y - y_per_pix/2.0 - trap_left_y) \n" + " / trap_left_slope; \n" + " x_bottom_cut_left = trap_left_x \n" + " + (source_texture.y + y_per_pix/2.0 - trap_left_y) \n" + " / trap_left_slope; \n" + " } \n" + " \n" + " if(trap_right_vertical == 1) { \n" + " x_up_cut_right = trap_right_x; \n" + " x_bottom_cut_right = trap_right_x; \n" + " } else { \n" + " x_up_cut_right = trap_right_x \n" + " + (source_texture.y - y_per_pix/2.0 - trap_right_y) \n" + " / trap_right_slope; \n" + " x_bottom_cut_right = trap_right_x \n" + " + (source_texture.y + y_per_pix/2.0 - trap_right_y) \n" + " / trap_right_slope; \n" + " } \n" + " \n" + " if((x_up_cut_left <= source_texture.x - x_per_pix/2.0) && \n" + " (x_bottom_cut_left <= source_texture.x - x_per_pix/2.0) && \n" + " (x_up_cut_right >= source_texture.x + x_per_pix/2.0) && \n" + " (x_bottom_cut_right >= source_texture.x + x_per_pix/2.0) && \n" + " (trap_top <= source_texture.y - y_per_pix/2.0) && \n" + " (trap_bottom >= source_texture.y + y_per_pix/2.0)) { \n" + // The complete inside case. + " return 1.0; \n" + " } else if((trap_top > source_texture.y + y_per_pix/2.0) || \n" + " (trap_bottom < source_texture.y - y_per_pix/2.0)) { \n" + // The complete outside. Above the top or Below the bottom. + " return 0.0; \n" + " } else { \n" + " if((x_up_cut_right < source_texture.x - x_per_pix/2.0 && \n" + " x_bottom_cut_right < source_texture.x - x_per_pix/2.0) \n" + " || (x_up_cut_left > source_texture.x + x_per_pix/2.0 && \n" + " x_bottom_cut_left > source_texture.x + x_per_pix/2.0)) { \n" + // The complete outside. At Left or Right of the trapezoide. + " return 0.0; \n" + " } \n" + " } \n" + // Get here, the pix is partly inside the trapezoid. + " { \n" + " float percent = 0.0; \n" + " float up = (source_texture.y - y_per_pix/2.0) >= trap_top ? \n" + " (source_texture.y - y_per_pix/2.0) : trap_top; \n" + " float bottom = (source_texture.y + y_per_pix/2.0) <= trap_bottom ? \n" + " (source_texture.y + y_per_pix/2.0) : trap_bottom; \n" + " float left = source_texture.x - x_per_pix/2.0; \n" + " float right = source_texture.x + x_per_pix/2.0; \n" + " \n" + " percent = (bottom - up) / y_per_pix; \n" + " \n" + " if(trap_left_vertical == 1) { \n" + " if(trap_left_x > source_texture.x - x_per_pix/2.0 && \n" + " trap_left_x < source_texture.x + x_per_pix/2.0) \n" + " left = trap_left_x; \n" + " } \n" + " if(trap_right_vertical == 1) { \n" + " if(trap_right_x > source_texture.x - x_per_pix/2.0 && \n" + " trap_right_x < source_texture.x + x_per_pix/2.0) \n" + " right = trap_right_x; \n" + " } \n" + " if((up >= bottom) || (left >= right)) \n" + " return 0.0; \n" + " \n" + " percent = percent * ((right - left)/x_per_pix); \n" + " if(trap_left_vertical == 1 && trap_right_vertical == 1) \n" + " return percent; \n" + " \n" + " if(trap_left_vertical != 1) { \n" + " float area; \n" + // the slope should never be 0.0 here + " float up_x = trap_left_x + (up - trap_left_y)/trap_left_slope; \n" + " float bottom_x = trap_left_x + (bottom - trap_left_y)/trap_left_slope; \n" + " if(trap_left_slope < 0.0 && up_x > left) { \n" + /* case 1 + | + ----+-------------------------------------> + | / + | / + | +---/--------+ + | | /.........| + | | /..........| + | |/...........| + | /............| + | /|............| + | +------------+ + | + \|/ + */ + " float left_y = trap_left_y + trap_left_slope*(left - trap_left_x); \n" + " if((up_x > left) && (left_y > up)) { \n" + " area = 0.5 * (up_x - left) * (left_y - up); \n" + " if(up_x > right) { \n" + " float right_y = trap_left_y \n" + " + trap_left_slope*(right - trap_left_x); \n" + " area = area - 0.5 * (up_x - right) * (right_y - up); \n" + " } \n" + " if(left_y > bottom) { \n" + " area = area - 0.5 * (bottom_x - left) * (left_y - bottom); \n" + " } \n" + " } else { \n" + " area = 0.0; \n" + " } \n" + " percent = percent * (1.0 - (area/((right-left)*(bottom-up)))); \n" + " } else if(trap_left_slope > 0.0 && bottom_x > left) { \n" + /* case 2 + | + ----+-------------------------------------> + | \ + | \ + | +\-----------+ + | | \..........| + | | \.........| + | | \........| + | | \.......| + | | \......| + | +------\-----+ + | \ + | \ + \|/ + */ + " float right_y = trap_left_y + trap_left_slope*(right - trap_left_x); \n" + " if((up_x < right) && (right_y > up)) { \n" + " area = 0.5 * (right - up_x) * (right_y - up); \n" + " if(up_x < left) { \n" + " float left_y = trap_left_y \n" + " + trap_left_slope*(left - trap_left_x); \n" + " area = area - 0.5 * (left - up_x) * (left_y - up); \n" + " } \n" + " if(right_y > bottom) { \n" + " area = area - 0.5 * (right - bottom_x) * (right_y - bottom); \n" + " } \n" + " } else { \n" + " area = 0.0; \n" + " } \n" + " percent = percent * (area/((right-left)*(bottom-up))); \n" + " } \n" + " } \n" + " \n" + " if(trap_right_vertical != 1) { \n" + " float area; \n" + // the slope should never be 0.0 here + " float up_x = trap_right_x + (up - trap_right_y)/trap_right_slope; \n" + " float bottom_x = trap_right_x + (bottom - trap_right_y)/trap_right_slope; \n" + " if(trap_right_slope < 0.0 && bottom_x < right) { \n" + /* case 3 + | + ----+-------------------------------------> + | / + | +--------/---+ + | |......./ | + | |....../ | + | |...../ | + | |..../ | + | |.../ | + | +--/---------+ + | / + | + \|/ + */ + " float left_y = trap_right_y + trap_right_slope*(left - trap_right_x); \n" + " if((up_x > left) && (left_y > up)) { \n" + " area = 0.5 * (up_x - left) * (left_y - up); \n" + " if(up_x > right) { \n" + " float right_y = trap_right_y \n" + " + trap_right_slope*(right - trap_right_x); \n" + " area = area - 0.5 * (up_x - right) * (right_y - up); \n" + " } \n" + " if(left_y > bottom) { \n" + " area = area - 0.5 * (bottom_x - left) * (left_y - bottom); \n" + " } \n" + " } else { \n" + " area = 0.0; \n" + " } \n" + " percent = percent * (area/((right-left)*(bottom-up))); \n" + " } else if(trap_right_slope > 0.0 && up_x < right) { \n" + /* case 4 + | + ----+-------------------------------------> + | \ + | +--------\---+ + | |.........\ | + | |..........\ | + | |...........\| + | |............\ + | |............|\ + | +------------+ \ + | \ + | + \|/ + */ + " float right_y = trap_right_y + trap_right_slope*(right - trap_right_x); \n" + " if((up_x < right) && (right_y > up)) { \n" + " area = 0.5 * (right - up_x) * (right_y - up); \n" + " if(up_x < left) { \n" + " float left_y = trap_right_y \n" + " + trap_right_slope*(left - trap_right_x); \n" + " area = area - 0.5 * (left - up_x) * (left_y - up); \n" + " } \n" + " if(right_y > bottom) { \n" + " area = area - 0.5 * (right - bottom_x) * (right_y - bottom); \n" + " } \n" + " } else { \n" + " area = 0.0; \n" + " } \n" + " percent = percent * (1.0 - (area/((right-left)*(bottom-up)))); \n" + " } \n" + " } \n" + " \n" + " return percent; \n" + " } \n" + "} \n" + "\n" + "void main() \n" + "{ \n" + " float alpha_val = get_alpha_val(); \n" + " gl_FragColor = vec4(0.0, 0.0, 0.0, alpha_val); \n" + "}\n"; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + glamor_priv->trapezoid_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, + GL_VERTEX_SHADER, trapezoid_vs); + fs_prog = glamor_compile_glsl_prog(dispatch, + GL_FRAGMENT_SHADER, trapezoid_fs); + + dispatch->glAttachShader(glamor_priv->trapezoid_prog, vs_prog); + dispatch->glAttachShader(glamor_priv->trapezoid_prog, fs_prog); + + dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, + GLAMOR_VERTEX_POS, "v_positionsition"); + dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, + GLAMOR_VERTEX_SOURCE, "v_texcoord"); + + glamor_link_glsl_prog(dispatch, glamor_priv->trapezoid_prog); + + dispatch->glUseProgram(0); + + glamor_put_dispatch(glamor_priv); +} + +void +glamor_fini_trapezoid_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glDeleteProgram(glamor_priv->trapezoid_prog); + glamor_put_dispatch(glamor_priv); +} + +static Bool +_glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, + xTrapezoid * traps, int ntrap, BoxRec *bounds) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + glamor_pixmap_private *pixmap_priv; + PixmapPtr pixmap = NULL; + GLint x_per_pix_uniform_location; + GLint y_per_pix_uniform_location; + GLint trap_top_uniform_location; + GLint trap_bottom_uniform_location; + GLint trap_left_x_uniform_location; + GLint trap_left_y_uniform_location; + GLint trap_left_slope_uniform_location; + GLint trap_right_x_uniform_location; + GLint trap_right_y_uniform_location; + GLint trap_right_slope_uniform_location; + GLint trap_left_vertical_uniform_location; + GLint trap_right_vertical_uniform_location; + GLint trapezoid_prog; + float width, height; + xFixed width_fix, height_fix; + GLfloat xscale, yscale; + float left_slope, right_slope; + xTrapezoid *ptrap; + BoxRec one_trap_bound; + float vertices[8]; + float tex_vertices[8]; + float tmp; + int i; + + glamor_priv = glamor_get_screen_private(screen); + trapezoid_prog = glamor_priv->trapezoid_prog; + + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ + DEBUGF("GLAMOR_PIXMAP_PRIV_HAS_FBO check failed, fallback\n"); + return FALSE; + } + + /* First, clear all to zero */ + if (!glamor_solid(pixmap, 0, 0, pixmap_priv->container->drawable.width, + pixmap_priv->container->drawable.height, + GXclear, 0xFFFFFFFF, 0)) { + DEBUGF("glamor_solid failed, fallback\n"); + return FALSE; + } + + dispatch = glamor_get_dispatch(glamor_priv); + + /* Bind all the uniform vars .*/ + x_per_pix_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "x_per_pix"); + y_per_pix_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "y_per_pix"); + trap_top_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_top"); + trap_bottom_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_bottom"); + trap_left_x_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_x"); + trap_left_y_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_y"); + trap_left_slope_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_slope"); + trap_left_vertical_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_vertical"); + trap_right_x_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_x"); + trap_right_y_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_y"); + trap_right_slope_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_slope"); + trap_right_vertical_uniform_location = + dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_vertical"); + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale)); + + width = (float)(bounds->x2 - bounds->x1); + height = (float)(bounds->y2 - bounds->y1); + width_fix = IntToxFixed((bounds->x2 - bounds->x1)); + height_fix = IntToxFixed((bounds->y2 - bounds->y1)); + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + /* Now draw the Trapezoid mask. */ + dispatch->glUseProgram(trapezoid_prog); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 0, vertices); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, 0, tex_vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + + dispatch->glEnable(GL_BLEND); + dispatch->glBlendFunc(GL_ONE, GL_ONE); + + for (i = 0; i < ntrap; i++) { + ptrap = traps + i; + + DEBUGF("--- The parameter of xTrapezoid is:\ntop: %d 0x%x\tbottom: %d 0x%x\n" + "left: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n" + "right: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n", + xFixedToInt(ptrap->top), ptrap->top, + xFixedToInt(ptrap->bottom), ptrap->bottom, + xFixedToInt(ptrap->left.p1.x), ptrap->left.p1.x, + xFixedToInt(ptrap->left.p1.y), ptrap->left.p1.y, + xFixedToInt(ptrap->left.p2.x), ptrap->left.p2.x, + xFixedToInt(ptrap->left.p2.y), ptrap->left.p2.y, + xFixedToInt(ptrap->right.p1.x), ptrap->right.p1.x, + xFixedToInt(ptrap->right.p1.y), ptrap->right.p1.y, + xFixedToInt(ptrap->right.p2.x), ptrap->right.p2.x, + xFixedToInt(ptrap->right.p2.y), ptrap->right.p2.y); + + miTrapezoidBounds(1, ptrap, &one_trap_bound); + glamor_set_tcoords((pixmap_priv->container->drawable.width), + (pixmap_priv->container->drawable.height), + (one_trap_bound.x1), + (one_trap_bound.y1), + (one_trap_bound.x2), + (one_trap_bound.y2), + glamor_priv->yInverted, tex_vertices); + + /* Need to rebase. */ + one_trap_bound.x1 -= bounds->x1; + one_trap_bound.x2 -= bounds->x1; + one_trap_bound.y1 -= bounds->y1; + one_trap_bound.y2 -= bounds->y1; + glamor_set_normalize_vcoords(xscale, yscale, + one_trap_bound.x1, one_trap_bound.y1, + one_trap_bound.x2, one_trap_bound.y2, + glamor_priv->yInverted, vertices); + + /* Swap the vtx for triangle render. */ + tmp = vertices[4]; + vertices[4] = vertices[6]; + vertices[6] = tmp; + tmp = vertices[5]; + vertices[5] = vertices[7]; + vertices[7] = tmp; + + tmp = tex_vertices[4]; + tex_vertices[4] = tex_vertices[6]; + tex_vertices[6] = tmp; + tmp = tex_vertices[5]; + tex_vertices[5] = tex_vertices[7]; + tex_vertices[7] = tmp; + + DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + vertices[0], vertices[1], vertices[2], vertices[3], + vertices[4], vertices[5], vertices[6], vertices[7]); + DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], + tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); + + if (ptrap->left.p1.x == ptrap->left.p2.x) { + left_slope = 0.0; + dispatch->glUniform1i(trap_left_vertical_uniform_location, 1); + } else { + left_slope = ((float)(ptrap->left.p1.y - ptrap->left.p2.y)) + / ((float)(ptrap->left.p1.x - ptrap->left.p2.x)); + dispatch->glUniform1i(trap_left_vertical_uniform_location, 0); + } + dispatch->glUniform1f(trap_left_slope_uniform_location, left_slope); + + if (ptrap->right.p1.x == ptrap->right.p2.x) { + right_slope = 0.0; + dispatch->glUniform1i(trap_right_vertical_uniform_location, 1); + } else { + right_slope = ((float)(ptrap->right.p1.y - ptrap->right.p2.y)) + / ((float)(ptrap->right.p1.x - ptrap->right.p2.x)); + dispatch->glUniform1i(trap_right_vertical_uniform_location, 0); + } + dispatch->glUniform1f(trap_right_slope_uniform_location, right_slope); + + dispatch->glUniform1f(x_per_pix_uniform_location, + ((float)width_fix) / (65536 * width)); + dispatch->glUniform1f(y_per_pix_uniform_location, + ((float)height_fix) / (65536 * height)); + + dispatch->glUniform1f(trap_top_uniform_location, + ((float)ptrap->top) / 65536); + dispatch->glUniform1f(trap_bottom_uniform_location, + ((float)ptrap->bottom) / 65536); + + dispatch->glUniform1f(trap_left_x_uniform_location, + ((float)ptrap->left.p1.x) / 65536); + dispatch->glUniform1f(trap_left_y_uniform_location, + ((float)ptrap->left.p1.y) / 65536); + dispatch->glUniform1f(trap_right_x_uniform_location, + ((float)ptrap->right.p1.x) / 65536); + dispatch->glUniform1f(trap_right_y_uniform_location, + ((float)ptrap->right.p1.y) / 65536); + + DEBUGF("x_per_pix = %f, y_per_pix = %f, trap_top = %f, trap_bottom = %f, " + "trap_left_x = %f, trap_left_y = %f, left_slope = %f, " + "trap_right_x = %f, trap_right_y = %f, right_slope = %f\n", + ((float)width_fix) / (65536*width), ((float)height_fix) / (65536*height), + ((float)ptrap->top) / 65536, ((float)ptrap->bottom) / 65536, + ((float)ptrap->left.p1.x) / 65536, ((float)ptrap->left.p1.y) / 65536, + left_slope, + ((float)ptrap->right.p1.x) / 65536, ((float)ptrap->right.p1.y) / 65536, + right_slope); + + /* Now rendering. */ + dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + dispatch->glBlendFunc(GL_ONE, GL_ZERO); + dispatch->glDisable(GL_BLEND); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); + return TRUE; +} + +#endif /*GLAMOR_TRAPEZOID_SHADER */ + /** - * Creates an appropriate picture to upload our alpha mask into (which - * we calculated in system memory) + * Creates an appropriate picture for temp mask use. */ static PicturePtr glamor_create_mask_picture(ScreenPtr screen, - PicturePtr dst, - PictFormatPtr pict_format, - CARD16 width, CARD16 height) + PicturePtr dst, + PictFormatPtr pict_format, + CARD16 width, CARD16 height, int gpu) { PixmapPtr pixmap; PicturePtr picture; @@ -61,26 +622,33 @@ glamor_create_mask_picture(ScreenPtr screen, return 0; } - pixmap = glamor_create_pixmap(screen, 0, 0, - pict_format->depth, - GLAMOR_CREATE_PIXMAP_CPU); + if (gpu) { + pixmap = glamor_create_pixmap(screen, width, height, + pict_format->depth, 0); + } else { + pixmap = glamor_create_pixmap(screen, 0, 0, + pict_format->depth, + GLAMOR_CREATE_PIXMAP_CPU); + } + if (!pixmap) return 0; picture = CreatePicture(0, &pixmap->drawable, pict_format, - 0, 0, serverClient, &error); - screen->DestroyPixmap(pixmap); + 0, 0, serverClient, &error); + glamor_destroy_pixmap(pixmap); return picture; } /** - * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid - * accumulation in system memory. + * glamor_trapezoids will first try to create a trapezoid mask using shader, + * if failed, miTrapezoids will generate trapezoid mask accumulating in + * system memory. */ static Bool _glamor_trapezoids(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps, Bool fallback) + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps, Bool fallback) { ScreenPtr screen = dst->pDrawable->pScreen; BoxRec bounds; @@ -89,7 +657,8 @@ _glamor_trapezoids(CARD8 op, INT16 x_rel, y_rel; int width, height, stride; PixmapPtr pixmap; - pixman_image_t *image; + pixman_image_t *image = NULL; + int ret = 0; /* 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. @@ -103,11 +672,14 @@ _glamor_trapezoids(CARD8 op, PictureMatchFormat(screen, 8, PICT_a8); for (; ntrap; ntrap--, traps++) glamor_trapezoids(op, src, dst, mask_format, x_src, - y_src, 1, traps); + y_src, 1, traps); return TRUE; } miTrapezoidBounds(ntrap, traps, &bounds); + DEBUGF("The bounds for all traps is: bounds.x1 = %d, bounds.x2 = %d, " + "bounds.y1 = %d, bounds.y2 = %d\n", bounds.x1, bounds.x2, + bounds.y1, bounds.y2); if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) return TRUE; @@ -118,41 +690,63 @@ _glamor_trapezoids(CARD8 op, width = bounds.x2 - bounds.x1; height = bounds.y2 - bounds.y1; stride = PixmapBytePad(width, mask_format->depth); + +#ifdef GLAMOR_TRAPEZOID_SHADER picture = glamor_create_mask_picture(screen, dst, mask_format, - width, height); + width, height, 1); if (!picture) return TRUE; - image = pixman_image_create_bits(picture->format, - width, height, NULL, stride); - if (!image) { + ret = _glamor_generate_trapezoid_with_shader(screen, picture, traps, ntrap, &bounds); + + if (!ret) FreePicture(picture, 0); - return TRUE; +#endif + + if (!ret) { + DEBUGF("Fallback to sw rasterize of trapezoid\n"); + + picture = glamor_create_mask_picture(screen, dst, mask_format, + width, height, 0); + if (!picture) + return TRUE; + + image = pixman_image_create_bits(picture->format, + width, height, NULL, stride); + if (!image) { + FreePicture(picture, 0); + return TRUE; + } + + for (; ntrap; ntrap--, traps++) + pixman_rasterize_trapezoid(image, + (pixman_trapezoid_t *) traps, + -bounds.x1, -bounds.y1); + + pixmap = glamor_get_drawable_pixmap(picture->pDrawable); + + screen->ModifyPixmapHeader(pixmap, width, height, + mask_format->depth, + BitsPerPixel(mask_format->depth), + PixmapBytePad(width, + mask_format->depth), + pixman_image_get_data(image)); } - for (; ntrap; ntrap--, traps++) - pixman_rasterize_trapezoid(image, - (pixman_trapezoid_t *) traps, - -bounds.x1, -bounds.y1); - - pixmap = glamor_get_drawable_pixmap(picture->pDrawable); - - screen->ModifyPixmapHeader(pixmap, width, height, - mask_format->depth, - BitsPerPixel(mask_format->depth), - PixmapBytePad(width, - mask_format->depth), - pixman_image_get_data(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); + DEBUGF("x_src = %d, y_src = %d, x_dst = %d, y_dst = %d, " + "x_rel = %d, y_rel = %d\n", x_src, y_src, x_dst, + y_dst, x_rel, y_rel); - pixman_image_unref(image); + CompositePicture(op, src, picture, dst, + x_rel, y_rel, + 0, 0, + bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + + if (image) + pixman_image_unref(image); FreePicture(picture, 0); return TRUE; @@ -160,22 +754,26 @@ _glamor_trapezoids(CARD8 op, void glamor_trapezoids(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps) + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) { + DEBUGF("x_src = %d, y_src = %d, ntrap = %d\n", x_src, y_src, ntrap); + _glamor_trapezoids(op, src, dst, mask_format, x_src, - y_src, ntrap, traps, TRUE); + y_src, ntrap, traps, TRUE); } Bool glamor_trapezoids_nf(CARD8 op, - PicturePtr src, PicturePtr dst, - PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int ntrap, xTrapezoid * traps) + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) { + DEBUGF("x_src = %d, y_src = %d, ntrap = %d\n", x_src, y_src, ntrap); + return _glamor_trapezoids(op, src, dst, mask_format, x_src, - y_src, ntrap, traps, FALSE); + y_src, ntrap, traps, FALSE); } #endif /* RENDER */ From 0b0391765f3ca0192b00f4970c9453934d529397 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Mon, 4 Jun 2012 03:18:40 +0800 Subject: [PATCH 391/462] Add macro of vertex setting for triangle stripe Add macro of vertex setting for triangle stripe draw, and make the code clear. Signed-off-by: Junyan He --- glamor/glamor_gradient.c | 47 +++++++++++--------------------- glamor/glamor_trapezoid.c | 31 ++++++--------------- glamor/glamor_utils.h | 57 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 54 deletions(-) diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index 09e33d7ce..e02c12cef 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -806,25 +806,25 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, *xscale, *yscale, x_source, y_source, dst_picture->pDrawable->width, dst_picture->pDrawable->height); - glamor_set_normalize_vcoords(pixmap_priv, *xscale, *yscale, - 0, 0, - (INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - glamor_priv->yInverted, vertices); + glamor_set_normalize_vcoords_tri_strip(*xscale, *yscale, + 0, 0, + (INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), + glamor_priv->yInverted, vertices); if (tex_normalize) { - glamor_set_normalize_tcoords(pixmap_priv, *xscale, *yscale, - x_source, y_source, - (INT16)(dst_picture->pDrawable->width + x_source), - (INT16)(dst_picture->pDrawable->height + y_source), - glamor_priv->yInverted, tex_vertices); + glamor_set_normalize_tcoords_tri_stripe(*xscale, *yscale, + x_source, y_source, + (INT16)(dst_picture->pDrawable->width + x_source), + (INT16)(dst_picture->pDrawable->height + y_source), + glamor_priv->yInverted, tex_vertices); } else { - glamor_set_tcoords((INT16)(dst_picture->pDrawable->width), - (INT16)(dst_picture->pDrawable->height), - x_source, y_source, - (INT16)(dst_picture->pDrawable->width) + x_source, - (INT16)(dst_picture->pDrawable->height) + y_source, - glamor_priv->yInverted, tex_vertices); + glamor_set_tcoords_tri_strip((INT16)(dst_picture->pDrawable->width), + (INT16)(dst_picture->pDrawable->height), + x_source, y_source, + (INT16)(dst_picture->pDrawable->width) + x_source, + (INT16)(dst_picture->pDrawable->height) + y_source, + glamor_priv->yInverted, tex_vertices); } DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," @@ -836,21 +836,6 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); - /* Swap the vtx for triangle render. */ - tmp = vertices[4]; - vertices[4] = vertices[6]; - vertices[6] = tmp; - tmp = vertices[5]; - vertices[5] = vertices[7]; - vertices[7] = tmp; - - tmp = tex_vertices[4]; - tex_vertices[4] = tex_vertices[6]; - tex_vertices[6] = tmp; - tmp = tex_vertices[5]; - tex_vertices[5] = tex_vertices[7]; - tex_vertices[7] = tmp; - dispatch = glamor_get_dispatch(glamor_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index d9682baa8..e65f7e39b 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -490,39 +490,24 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, xFixedToInt(ptrap->right.p2.y), ptrap->right.p2.y); miTrapezoidBounds(1, ptrap, &one_trap_bound); - glamor_set_tcoords((pixmap_priv->container->drawable.width), - (pixmap_priv->container->drawable.height), - (one_trap_bound.x1), - (one_trap_bound.y1), - (one_trap_bound.x2), - (one_trap_bound.y2), - glamor_priv->yInverted, tex_vertices); + glamor_set_tcoords_tri_strip((pixmap_priv->container->drawable.width), + (pixmap_priv->container->drawable.height), + (one_trap_bound.x1), + (one_trap_bound.y1), + (one_trap_bound.x2), + (one_trap_bound.y2), + glamor_priv->yInverted, tex_vertices); /* Need to rebase. */ one_trap_bound.x1 -= bounds->x1; one_trap_bound.x2 -= bounds->x1; one_trap_bound.y1 -= bounds->y1; one_trap_bound.y2 -= bounds->y1; - glamor_set_normalize_vcoords(xscale, yscale, + glamor_set_normalize_vcoords_tri_strip(xscale, yscale, one_trap_bound.x1, one_trap_bound.y1, one_trap_bound.x2, one_trap_bound.y2, glamor_priv->yInverted, vertices); - /* Swap the vtx for triangle render. */ - tmp = vertices[4]; - vertices[4] = vertices[6]; - vertices[6] = tmp; - tmp = vertices[5]; - vertices[5] = vertices[7]; - vertices[7] = tmp; - - tmp = tex_vertices[4]; - tex_vertices[4] = tex_vertices[6]; - tex_vertices[6] = tmp; - tmp = tex_vertices[5]; - tex_vertices[5] = tex_vertices[7]; - tex_vertices[7] = tmp; - DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," "rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0], vertices[1], vertices[2], vertices[3], diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 18f7f3b10..dfe8e568f 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -481,6 +481,25 @@ tx2, ty2, yInverted, vertices); \ } while(0) +#define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = t_from_x_coord_x(xscale, x1); \ + (vertices)[2] = t_from_x_coord_x(xscale, x2); \ + (vertices)[6] = (vertices)[2]; \ + (vertices)[4] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \ + (vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \ + } \ + else { \ + (vertices)[1] = t_from_x_coord_y(yscale, y1); \ + (vertices)[7] = t_from_x_coord_y(yscale, y2); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[5] = (vertices)[7]; \ + } while(0) #define glamor_set_tcoords(width, height, x1, y1, x2, y2, \ yInverted, vertices) \ @@ -501,6 +520,24 @@ (vertices)[7] = (vertices)[5]; \ } while(0) +#define glamor_set_tcoords_tri_strip(width, height, x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = (x1); \ + (vertices)[2] = (x2); \ + (vertices)[6] = (vertices)[2]; \ + (vertices)[4] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = (y1); \ + (vertices)[7] = (y2); \ + } \ + else { \ + (vertices)[1] = height - (y2); \ + (vertices)[7] = height - (y1); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[5] = (vertices)[7]; \ + } while(0) #define glamor_set_normalize_vcoords(priv, xscale, yscale, \ x1, y1, x2, y2, \ @@ -524,6 +561,26 @@ (vertices)[7] = (vertices)[5]; \ } while(0) +#define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = v_from_x_coord_x(xscale, x1); \ + (vertices)[2] = v_from_x_coord_x(xscale, x2); \ + (vertices)[6] = (vertices)[2]; \ + (vertices)[4] = (vertices)[0]; \ + if (yInverted) { \ + (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ + (vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \ + } \ + else { \ + (vertices)[1] = v_from_x_coord_y(yscale, y1); \ + (vertices)[7] = v_from_x_coord_y(yscale, y2); \ + } \ + (vertices)[3] = (vertices)[1]; \ + (vertices)[5] = (vertices)[7]; \ + } while(0) + #define glamor_set_normalize_pt(xscale, yscale, x, y, \ yInverted, pt) \ do { \ From 5f1560c84aa386bb12dc6ec3daeb93e0f63c09c2 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Mon, 4 Jun 2012 07:22:27 +0800 Subject: [PATCH 392/462] Modilfy the composite logic to two phases We seperate the composite to two phases, firstly to select the shader according to source type and logic op, setting the right parameters. Then we emit the vertex array to generate the dest result. The reason why we do this is that the shader may be used to composite no only rect, trapezoid and triangle render function can also use it to render triangles and polygens. The old function glamor_composite_with_shader do the whole two phases work and can not match the new request. Signed-off-by: Junyan He --- glamor/glamor_gradient.c | 1 - glamor/glamor_priv.h | 21 ++++- glamor/glamor_render.c | 184 +++++++++++++++++++++++--------------- glamor/glamor_trapezoid.c | 9 +- 4 files changed, 134 insertions(+), 81 deletions(-) diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index e02c12cef..444ba6cb9 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -788,7 +788,6 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen, glamor_pixmap_private *pixmap_priv; PixmapPtr pixmap = NULL; glamor_gl_dispatch *dispatch = NULL; - float tmp; pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b842d9b39..362abae76 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -127,6 +127,12 @@ enum shader_in { SHADER_IN_COUNT, }; +struct shader_key { + enum shader_source source; + enum shader_mask mask; + enum shader_in in; +}; + enum gradient_shader { SHADER_GRADIENT_LINEAR, SHADER_GRADIENT_RADIAL, @@ -158,6 +164,8 @@ enum glamor_gl_flavor { #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 +#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 + typedef struct { PicturePtr picture; /* Where the glyphs of the cache are stored */ GlyphPtr *glyphs; @@ -704,6 +712,15 @@ void glamor_composite_rects (CARD8 op, xRectangle *rects); void glamor_init_trapezoid_shader(ScreenPtr screen); void glamor_fini_trapezoid_shader(ScreenPtr screen); +PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, + PicturePtr source, + int x_source, + int y_source, int width, int height); +void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts); +void glamor_emit_composite_vert(ScreenPtr screen, + const float *src_coords, + const float *mask_coords, + const float *dst_coords, int i); /* glamor_trapezoid.c */ void glamor_trapezoids(CARD8 op, @@ -939,10 +956,10 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER -//#define GLAMOR_TRAPEZOID_SHADER +#define GLAMOR_TRAPEZOID_SHADER #endif #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 -#if 1 +#if 0 #define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index da9d847da..a228a22e6 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -43,11 +43,6 @@ //#define DEBUGRegionPrint(x) do {} while (0) #define DEBUGRegionPrint RegionPrint #endif -struct shader_key { - enum shader_source source; - enum shader_mask mask; - enum shader_in in; -}; struct blendinfo { Bool dest_alpha; @@ -385,8 +380,6 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct return shader; } -#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 - static void glamor_init_eb(unsigned short *eb, int vert_cnt) { @@ -735,7 +728,7 @@ cleanup_region: return ret; } -static void +void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) { glamor_screen_private *glamor_priv = @@ -795,7 +788,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) glamor_put_dispatch(glamor_priv); } -static void +void glamor_emit_composite_vert(ScreenPtr screen, const float *src_coords, const float *mask_coords, @@ -963,44 +956,36 @@ glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, texcoords); } -static Bool -glamor_composite_with_shader(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - glamor_pixmap_private *source_pixmap_priv, - glamor_pixmap_private *mask_pixmap_priv, - glamor_pixmap_private *dest_pixmap_priv, - int nrect, - glamor_composite_rect_t * rects) +Bool glamor_composite_choose_shader(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + struct shader_key *s_key, + PictFormatShort *psaved_source_format) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; - glamor_gl_dispatch *dispatch; PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; - PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; - GLfloat dst_xscale, dst_yscale; - GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; - struct shader_key key; - glamor_composite_shader *shader; - float vertices[8], source_texcoords[8], mask_texcoords[8]; - int dest_x_off, dest_y_off; - int source_x_off, source_y_off; - int mask_x_off, mask_y_off; + PixmapPtr source_pixmap = NULL; + PixmapPtr mask_pixmap = NULL; enum glamor_pixmap_status source_status = GLAMOR_NONE; enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; - float src_matrix[9], mask_matrix[9]; - float *psrc_matrix = NULL, *pmask_matrix = NULL; - GLfloat source_solid_color[4], mask_solid_color[4]; - int vert_stride = 4; - int nrect_max; + struct shader_key key; + GLfloat source_solid_color[4]; + GLfloat mask_solid_color[4]; + glamor_composite_shader *shader = NULL; + glamor_gl_dispatch *dispatch = NULL; Bool ret = FALSE; 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) { key.source = SHADER_SOURCE_SOLID; @@ -1023,10 +1008,11 @@ glamor_composite_with_shader(CARD8 op, } else { key.source = SHADER_SOURCE_TEXTURE_ALPHA; } + if (mask) { if (!mask->pDrawable) { if (mask->pSourcePict->type == - SourcePictTypeSolidFill) { + SourcePictTypeSolidFill) { key.mask = SHADER_MASK_SOLID; glamor_get_rgba_from_pixel (mask->pSourcePict->solidFill.color, @@ -1045,14 +1031,13 @@ glamor_composite_with_shader(CARD8 op, if (op == PictOpClear) key.mask = SHADER_MASK_NONE; else if (op == PictOpSrc || op == PictOpAdd - || op == PictOpIn || op == PictOpOut - || op == PictOpOverReverse) + || op == PictOpIn || op == PictOpOut + || op == PictOpOverReverse) key.in = SHADER_IN_CA_SOURCE; else if (op == PictOpOutReverse || op == PictOpInReverse) { key.in = SHADER_IN_CA_ALPHA; } else { - glamor_fallback - ("Unsupported component alpha op: %d\n", op); + glamor_fallback("Unsupported component alpha op: %d\n", op); goto fail; } } @@ -1069,6 +1054,7 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("mask alphaMap\n"); goto fail; } + if (key.source == SHADER_SOURCE_TEXTURE || key.source == SHADER_SOURCE_TEXTURE_ALPHA) { source_pixmap = source_pixmap_priv->base.pixmap; @@ -1090,6 +1076,7 @@ glamor_composite_with_shader(CARD8 op, #endif } } + if (key.mask == SHADER_MASK_TEXTURE || key.mask == SHADER_MASK_TEXTURE_ALPHA) { mask_pixmap = mask_pixmap_priv->base.pixmap; @@ -1106,26 +1093,25 @@ glamor_composite_with_shader(CARD8 op, #endif } } + #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD if (source_status == GLAMOR_UPLOAD_PENDING - && mask_status == GLAMOR_UPLOAD_PENDING - && source_pixmap == mask_pixmap) { + && mask_status == GLAMOR_UPLOAD_PENDING + && source_pixmap == mask_pixmap) { if (source->format != mask->format) { saved_source_format = source->format; - 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); + 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); + glamor_picture_format_fixup(source, + source_pixmap_priv); } /* XXX * By default, glamor_upload_picture_to_texture will wire alpha to 1 @@ -1144,11 +1130,11 @@ glamor_composite_with_shader(CARD8 op, * **/ if (!PICT_FORMAT_A(saved_source_format) - && PICT_FORMAT_A(mask->format)) + && PICT_FORMAT_A(mask->format)) key.source = SHADER_SOURCE_TEXTURE; if (!PICT_FORMAT_A(mask->format) - && PICT_FORMAT_A(saved_source_format)) + && PICT_FORMAT_A(saved_source_format)) key.mask = SHADER_MASK_TEXTURE; mask_status = GLAMOR_NONE; @@ -1156,16 +1142,14 @@ glamor_composite_with_shader(CARD8 op, source_status = glamor_upload_picture_to_texture(source); if (source_status != GLAMOR_UPLOAD_DONE) { - glamor_fallback - ("Failed to upload source texture.\n"); + 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"); + glamor_fallback("Failed to upload source texture.\n"); goto fail; } } @@ -1173,8 +1157,7 @@ glamor_composite_with_shader(CARD8 op, 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"); + glamor_fallback("Failed to upload mask texture.\n"); goto fail; } } @@ -1206,8 +1189,8 @@ glamor_composite_with_shader(CARD8 op, shader = glamor_lookup_composite_shader(screen, &key); if (shader->prog == 0) { - glamor_fallback - ("no shader program for this render acccel mode\n"); + glamor_fallback("no shader program for this" + "render acccel mode\n"); goto fail; } @@ -1216,33 +1199,92 @@ glamor_composite_with_shader(CARD8 op, if (key.source == SHADER_SOURCE_SOLID) { glamor_set_composite_solid(dispatch, source_solid_color, - shader->source_uniform_location); + shader->source_uniform_location); } else { glamor_set_composite_texture(screen, 0, source, - source_pixmap_priv, shader->source_wh, - shader->source_repeat_mode); + source_pixmap_priv, shader->source_wh, + shader->source_repeat_mode); } + if (key.mask != SHADER_MASK_NONE) { if (key.mask == SHADER_MASK_SOLID) { glamor_set_composite_solid(dispatch, - mask_solid_color, - shader->mask_uniform_location); + mask_solid_color, + shader->mask_uniform_location); } else { glamor_set_composite_texture(screen, 1, mask, - mask_pixmap_priv, shader->mask_wh, - shader->mask_repeat_mode); + mask_pixmap_priv, shader->mask_wh, + shader->mask_repeat_mode); } } + glamor_put_dispatch(glamor_priv); + ret = TRUE; + memcpy(s_key, &key, sizeof(key)); + *psaved_source_format = saved_source_format; + goto done; + +fail: + if (saved_source_format) + source->format = saved_source_format; +done: + return ret; +} + +static Bool +glamor_composite_with_shader(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + int nrect, glamor_composite_rect_t * rects) +{ + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; + PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; + PixmapPtr source_pixmap = NULL; + PixmapPtr mask_pixmap = NULL; + glamor_gl_dispatch *dispatch = NULL; + GLfloat dst_xscale, dst_yscale; + GLfloat mask_xscale = 1, mask_yscale = 1, + src_xscale = 1, src_yscale = 1; + struct shader_key key; + float vertices[8], source_texcoords[8], mask_texcoords[8]; + int dest_x_off, dest_y_off; + int source_x_off, source_y_off; + int mask_x_off, mask_y_off; + PictFormatShort saved_source_format = 0; + float src_matrix[9], mask_matrix[9]; + float *psrc_matrix = NULL, *pmask_matrix = NULL; + int vert_stride = 4; + int nrect_max; + Bool ret = FALSE; + + if(!glamor_composite_choose_shader(op, source, mask, dest, + source_pixmap_priv, mask_pixmap_priv, + dest_pixmap_priv, + &key, &saved_source_format)) { + glamor_fallback("glamor_composite_choose_shader failed\n"); + return ret; + } + + dispatch = glamor_get_dispatch(glamor_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); + dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); glamor_get_drawable_deltas(dest->pDrawable, dest_pixmap, &dest_x_off, &dest_y_off); pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); if (glamor_priv->has_source_coords) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, &source_y_off); @@ -1256,6 +1298,8 @@ glamor_composite_with_shader(CARD8 op, } if (glamor_priv->has_mask_coords) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, @@ -1350,16 +1394,10 @@ glamor_composite_with_shader(CARD8 op, glamor_put_dispatch(glamor_priv); ret = TRUE; - goto done; - -fail: - if (saved_source_format) - source->format = saved_source_format; -done: return ret; } -static PicturePtr +PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr source, int x_source, diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index e65f7e39b..f0c0b8b2b 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -395,7 +395,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, BoxRec one_trap_bound; float vertices[8]; float tex_vertices[8]; - float tmp; int i; glamor_priv = glamor_get_screen_private(screen); @@ -410,8 +409,8 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, } /* First, clear all to zero */ - if (!glamor_solid(pixmap, 0, 0, pixmap_priv->container->drawable.width, - pixmap_priv->container->drawable.height, + if (!glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width, + pixmap_priv->base.pixmap->drawable.height, GXclear, 0xFFFFFFFF, 0)) { DEBUGF("glamor_solid failed, fallback\n"); return FALSE; @@ -490,8 +489,8 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, xFixedToInt(ptrap->right.p2.y), ptrap->right.p2.y); miTrapezoidBounds(1, ptrap, &one_trap_bound); - glamor_set_tcoords_tri_strip((pixmap_priv->container->drawable.width), - (pixmap_priv->container->drawable.height), + glamor_set_tcoords_tri_strip((pixmap_priv->base.pixmap->drawable.width), + (pixmap_priv->base.pixmap->drawable.height), (one_trap_bound.x1), (one_trap_bound.y1), (one_trap_bound.x2), From fa74a213ad175cb0920905a8011c62efdd348d45 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Mon, 4 Jun 2012 07:52:05 +0800 Subject: [PATCH 393/462] Add the trapezoid direct render logic We firstly get the render area by clipping the trapezoid with the clip rect, then split the clipped area into small triangles and use the composite logic to generate the result directly. This manner is fast but have the problem that some implementation of GL do not implement the Anti-Alias of triangles fill, so the edge sometimes has sawtooth. It is not acceptable when use trapezoid to approximate circles and wide lines. Signed-off-by: Junyan He --- glamor/glamor_priv.h | 9 + glamor/glamor_trapezoid.c | 733 ++++++++++++++++++++++++++++++++++++++ glamor/glamor_utils.h | 64 ++++ 3 files changed, 806 insertions(+) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 362abae76..1b45a71fe 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -716,6 +716,15 @@ PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr source, int x_source, int y_source, int width, int height); +Bool glamor_composite_choose_shader(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + glamor_pixmap_private *source_pixmap_priv, + glamor_pixmap_private *mask_pixmap_priv, + glamor_pixmap_private *dest_pixmap_priv, + struct shader_key *s_key, + PictFormatShort *psaved_source_format); void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts); void glamor_emit_composite_vert(ScreenPtr screen, const float *src_coords, diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index f0c0b8b2b..030e49030 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -37,6 +37,739 @@ #include "fbpict.h" #ifdef GLAMOR_TRAPEZOID_SHADER + +#define POINT_INSIDE_CLIP_RECT(point, rect) \ + (point[0] >= IntToxFixed(rect->x1) \ + && point[0] <= IntToxFixed(rect->x2) \ + && point[1] >= IntToxFixed(rect->y1) \ + && point[1] <= IntToxFixed(rect->y2)) + +static xFixed +_glamor_linefixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +static xFixed +_glamor_linefixedY (xLineFixed *l, xFixed x, Bool ceil) +{ + xFixed dy = l->p2.y - l->p1.y; + xFixed_32_32 ey = (xFixed_32_32) (x - l->p1.x) * dy; + xFixed dx = l->p2.x - l->p1.x; + if (ceil) + ey += (dx - 1); + return l->p1.y + (xFixed) (ey / dx); +} + +static Bool +point_inside_trapezoid(int point[2], xTrapezoid * trap) +{ + int ret = TRUE; + int tmp; + if (point[1] > trap->bottom + || point[1] < trap->top) + ret = FALSE; + + tmp = _glamor_linefixedX (&trap->left, point[1], FALSE); + if (point[0] < tmp) + ret = FALSE; + + tmp = _glamor_linefixedX (&trap->right, point[1], TRUE); + if (point[0] > tmp) + ret = FALSE; + + return ret; +} + +static void +glamor_emit_composite_triangle(ScreenPtr screen, + const float *src_coords, + const float *mask_coords, + const float *dst_coords) +{ + 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); +} + +static void +glamor_flush_composite_triangles(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch; + + if (!glamor_priv->render_nr_verts) + return; + + dispatch = glamor_get_dispatch(glamor_priv); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + else { + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } + + dispatch->glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts); + glamor_put_dispatch(glamor_priv); +} + +#define DEBUG_CLIP_VTX 0 + +static Bool +_glamor_clip_trapezoid_vertex(xTrapezoid * trap, BoxPtr pbox, + int vertex[6], int *num) +{ + int tl[2]; + int bl[2]; + int tr[2]; + int br[2]; + int left_cut_top[2]; + int left_cut_left[2]; + int left_cut_right[2]; + int left_cut_bottom[2]; + int right_cut_top[2]; + int right_cut_left[2]; + int right_cut_right[2]; + int right_cut_bottom[2]; + int tmp[2]; + int tmp_vtx[20*2]; + float tmp_vtx_slope[20]; + BoxRec trap_bound; + int i = 0; + int vertex_num = 0; + + if (DEBUG_CLIP_VTX) { + ErrorF("The parameter of xTrapezoid is:\ntop: %d 0x%x\tbottom: %d 0x%x\n" + "left: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n" + "right: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n", + xFixedToInt(trap->top), (unsigned int)trap->top, + xFixedToInt(trap->bottom), (unsigned int)trap->bottom, + xFixedToInt(trap->left.p1.x), (unsigned int)trap->left.p1.x, + xFixedToInt(trap->left.p1.y), (unsigned int)trap->left.p1.y, + xFixedToInt(trap->left.p2.x), (unsigned int)trap->left.p2.x, + xFixedToInt(trap->left.p2.y), (unsigned int)trap->left.p2.y, + xFixedToInt(trap->right.p1.x), (unsigned int)trap->right.p1.x, + xFixedToInt(trap->right.p1.y), (unsigned int)trap->right.p1.y, + xFixedToInt(trap->right.p2.x), (unsigned int)trap->right.p2.x, + xFixedToInt(trap->right.p2.y), (unsigned int)trap->right.p2.y); + } + + miTrapezoidBounds(1, trap, &trap_bound); + if (DEBUG_CLIP_VTX) + ErrorF("The bounds for this traps is: bounds.x1 = %d, bounds.x2 = %d, " + "bounds.y1 = %d, bounds.y2 = %d\n", trap_bound.x1, trap_bound.x2, + trap_bound.y1, trap_bound.y2); + + if (trap_bound.x1 > pbox->x2 || trap_bound.x2 < pbox->x1) + return FALSE; + if (trap_bound.y1 > pbox->y2 || trap_bound.y2 < pbox->y1) + return FALSE; + +#define IS_TRAP_EDGE_VERTICAL(edge) \ + (edge->p1.x == edge->p2.x) + +#define CACULATE_CUT_VERTEX(vtx, cal_x, ceil, vh_edge, edge) \ + do { \ + if(cal_x) { \ + vtx[1] = (vh_edge); \ + vtx[0] = (_glamor_linefixedX( \ + edge, vh_edge, ceil)); \ + if(DEBUG_CLIP_VTX) \ + ErrorF("The intersection point of line y=%d and " \ + "line of p1:(%d,%d) -- p2 (%d,%d) " \ + "is (%d, %d)\n", \ + xFixedToInt(vh_edge), \ + xFixedToInt(edge->p1.x), \ + xFixedToInt(edge->p1.y), \ + xFixedToInt(edge->p2.x), \ + xFixedToInt(edge->p2.y), \ + xFixedToInt(vtx[0]), \ + xFixedToInt(vtx[1])); \ + } else { \ + vtx[0] = (vh_edge); \ + vtx[1] = (_glamor_linefixedY( \ + edge, vh_edge, ceil)); \ + if(DEBUG_CLIP_VTX) \ + ErrorF("The intersection point of line x=%d and " \ + "line of p1:(%d,%d) -- p2 (%d,%d) " \ + "is (%d, %d)\n", \ + xFixedToInt(vh_edge), \ + xFixedToInt(edge->p1.x), \ + xFixedToInt(edge->p1.y), \ + xFixedToInt(edge->p2.x), \ + xFixedToInt(edge->p2.y), \ + xFixedToInt(vtx[0]), \ + xFixedToInt(vtx[1])); \ + } \ + } while(0) + +#define ADD_VERTEX_IF_INSIDE(vtx) \ + if(POINT_INSIDE_CLIP_RECT(vtx, pbox) \ + && point_inside_trapezoid(vtx, trap)){ \ + tmp_vtx[vertex_num] = xFixedToInt(vtx[0]); \ + tmp_vtx[vertex_num + 1] = xFixedToInt(vtx[1]); \ + vertex_num += 2; \ + if(DEBUG_CLIP_VTX) \ + ErrorF("@ Point: (%d, %d) is inside " \ + "the Rect and Trapezoid\n", \ + xFixedToInt(vtx[0]), \ + xFixedToInt(vtx[1])); \ + } else if(DEBUG_CLIP_VTX){ \ + ErrorF("X Point: (%d, %d) is outside " \ + "the Rect and Trapezoid\t", \ + xFixedToInt(vtx[0]), \ + xFixedToInt(vtx[1])); \ + if(POINT_INSIDE_CLIP_RECT(vtx, pbox)) \ + ErrorF("The Point is outside " \ + "the Trapezoid\n"); \ + else \ + ErrorF("The Point is outside " \ + "the Rect\n"); \ + } + + /*Trap's TopLeft, BottomLeft, TopRight and BottomRight. */ + CACULATE_CUT_VERTEX(tl, 1, FALSE, trap->top, (&trap->left)); + CACULATE_CUT_VERTEX(bl, 1, FALSE, trap->bottom, (&trap->left)); + CACULATE_CUT_VERTEX(tr, 1, TRUE, trap->top, (&trap->right)); + CACULATE_CUT_VERTEX(br, 1, TRUE, trap->bottom, (&trap->right)); + + if (DEBUG_CLIP_VTX) + ErrorF("Trap's TopLeft, BottomLeft, TopRight and BottomRight\n"); + if (DEBUG_CLIP_VTX) + ErrorF("Caculate the vertex of trapezoid:\n" + " (%3d, %3d)-------------------------(%3d, %3d)\n" + " / \\ \n" + " / \\ \n" + " / \\ \n" + " (%3d, %3d)---------------------------------(%3d, %3d)\n" + "Clip with rect:\n" + " (%3d, %3d)------------------------(%3d, %3d) \n" + " | | \n" + " | | \n" + " | | \n" + " (%3d, %3d)------------------------(%3d, %3d) \n", + xFixedToInt(tl[0]), xFixedToInt(tl[1]), xFixedToInt(tr[0]), + xFixedToInt(tr[1]), xFixedToInt(bl[0]), xFixedToInt(bl[1]), + xFixedToInt(br[0]), xFixedToInt(br[1]), + pbox->x1, pbox->y1, pbox->x2, pbox->y1, pbox->x1, pbox->y2, + pbox->x2, pbox->y2); + + ADD_VERTEX_IF_INSIDE(tl); + ADD_VERTEX_IF_INSIDE(bl); + ADD_VERTEX_IF_INSIDE(tr); + ADD_VERTEX_IF_INSIDE(br); + + /*Trap's left edge cut Rect. */ + if (DEBUG_CLIP_VTX) + ErrorF("Trap's left edge cut Rect\n"); + CACULATE_CUT_VERTEX(left_cut_top, 1, FALSE, IntToxFixed(pbox->y1), (&trap->left)); + ADD_VERTEX_IF_INSIDE(left_cut_top); + if (!IS_TRAP_EDGE_VERTICAL((&trap->left))) { + CACULATE_CUT_VERTEX(left_cut_left, 0, FALSE, IntToxFixed(pbox->x1), (&trap->left)); + ADD_VERTEX_IF_INSIDE(left_cut_left); + } + CACULATE_CUT_VERTEX(left_cut_bottom, 1, FALSE, IntToxFixed(pbox->y2), (&trap->left)); + ADD_VERTEX_IF_INSIDE(left_cut_bottom); + if (!IS_TRAP_EDGE_VERTICAL((&trap->left))) { + CACULATE_CUT_VERTEX(left_cut_right, 0, FALSE, IntToxFixed(pbox->x2), (&trap->left)); + ADD_VERTEX_IF_INSIDE(left_cut_right); + } + + /*Trap's right edge cut Rect. */ + if (DEBUG_CLIP_VTX) + ErrorF("Trap's right edge cut Rect\n"); + CACULATE_CUT_VERTEX(right_cut_top, 1, TRUE, IntToxFixed(pbox->y1), (&trap->right)); + ADD_VERTEX_IF_INSIDE(right_cut_top); + if (!IS_TRAP_EDGE_VERTICAL((&trap->right))) { + CACULATE_CUT_VERTEX(right_cut_left, 0, TRUE, IntToxFixed(pbox->x1), (&trap->right)); + ADD_VERTEX_IF_INSIDE(right_cut_left); + } + CACULATE_CUT_VERTEX(right_cut_bottom, 1, TRUE, IntToxFixed(pbox->y2), (&trap->right)); + ADD_VERTEX_IF_INSIDE(right_cut_bottom); + if (!IS_TRAP_EDGE_VERTICAL((&trap->right))) { + CACULATE_CUT_VERTEX(right_cut_right, 0, TRUE, IntToxFixed(pbox->x2), (&trap->right)); + ADD_VERTEX_IF_INSIDE(right_cut_right); + } + + /* Trap's top cut Left and Right of rect. */ + if (DEBUG_CLIP_VTX) + ErrorF("Trap's top cut Left and Right of rect\n"); + tmp[0] = IntToxFixed(pbox->x1); + tmp[1] = trap->top; + ADD_VERTEX_IF_INSIDE(tmp); + tmp[0] = IntToxFixed(pbox->x2); + tmp[1] = trap->top; + ADD_VERTEX_IF_INSIDE(tmp); + + /* Trap's bottom cut Left and Right of rect. */ + if (DEBUG_CLIP_VTX) + ErrorF("Trap's bottom cut Left and Right of rect\n"); + tmp[0] = IntToxFixed(pbox->x1); + tmp[1] = trap->bottom; + ADD_VERTEX_IF_INSIDE(tmp); + tmp[0] = IntToxFixed(pbox->x2); + tmp[1] = trap->bottom; + ADD_VERTEX_IF_INSIDE(tmp); + + /* The orginal 4 vertex of rect. */ + if (DEBUG_CLIP_VTX) + ErrorF("The orginal 4 vertex of rect\n"); + tmp[0] = IntToxFixed(pbox->x1); + tmp[1] = IntToxFixed(pbox->y1); + ADD_VERTEX_IF_INSIDE(tmp); + tmp[0] = IntToxFixed(pbox->x1); + tmp[1] = IntToxFixed(pbox->y2); + ADD_VERTEX_IF_INSIDE(tmp); + tmp[0] = IntToxFixed(pbox->x2); + tmp[1] = IntToxFixed(pbox->y2); + ADD_VERTEX_IF_INSIDE(tmp); + tmp[0] = IntToxFixed(pbox->x2); + tmp[1] = IntToxFixed(pbox->y1); + ADD_VERTEX_IF_INSIDE(tmp); + + if (DEBUG_CLIP_VTX) { + ErrorF("\nThe candidate vertex number is %d\n", vertex_num / 2); + for (i = 0; i < vertex_num / 2; i++) { + ErrorF("(%d, %d) ", tmp_vtx[2*i], tmp_vtx[2*i + 1]); + } + ErrorF("\n"); + } + + /* Sort the vertex by X and then Y. */ + for (i = 0; i < vertex_num / 2; i++) { + int j; + for (j = 0; j < vertex_num / 2 - i - 1; j++) { + if (tmp_vtx[2*j] > tmp_vtx[2*(j+1)] + || (tmp_vtx[2*j] == tmp_vtx[2*(j+1)] + && tmp_vtx[2*j + 1] > tmp_vtx[2*(j+1) + 1])) { + tmp[0] = tmp_vtx[2*j]; + tmp[1] = tmp_vtx[2*j + 1]; + tmp_vtx[2*j] = tmp_vtx[2*(j+1)]; + tmp_vtx[2*j + 1] = tmp_vtx[2*(j+1) + 1]; + tmp_vtx[2*(j+1)] = tmp[0]; + tmp_vtx[2*(j+1) + 1] = tmp[1]; + } + } + + } + + if (DEBUG_CLIP_VTX) { + ErrorF("\nAfter sort vertex number is:\n"); + for (i = 0; i < vertex_num / 2; i++) { + ErrorF("(%d, %d) ", tmp_vtx[2*i], tmp_vtx[2*i + 1]); + } + ErrorF("\n"); + } + + memset(vertex, -1, 2*6); + *num = 0; + + for (i = 0; i < vertex_num / 2; i++) { + if (*num > 0 && vertex[2*(*num - 1)] == tmp_vtx[2*i] + && vertex[2*(*num - 1) + 1] == tmp_vtx[2*i + 1]) { + /*same vertex.*/ + if (DEBUG_CLIP_VTX) + ErrorF("X Point:(%d, %d) discard\n", + tmp_vtx[2*i], tmp_vtx[2*i + 1]); + continue; + } + + (*num)++; + if (*num > 6) { + if (DEBUG_CLIP_VTX) + FatalError("Trapezoid clip with Rect can never have vtx" + "number bigger than 6\n"); + else { + ErrorF("Trapezoid clip with Rect can never have vtx" + "number bigger than 6\n"); + *num = 6; + break; + } + } + + vertex[2*(*num - 1)] = tmp_vtx[2*i]; + vertex[2*(*num - 1) + 1] = tmp_vtx[2*i + 1]; + if (DEBUG_CLIP_VTX) + ErrorF("@ Point:(%d, %d) select, num now is %d\n", + tmp_vtx[2*i], tmp_vtx[2*i + 1], *num); + } + + /* Now we need to arrange the vtx in the polygon's counter-clockwise + order. We first select the left and top point as the start point and + sort every vtx by the slope from vtx to the start vtx. */ + for (i = 1; i < *num; i++) { + tmp_vtx_slope[i] = (vertex[2*i] != vertex[0] ? + (float)(vertex[2*i + 1] - vertex[1]) / (float)(vertex[2*i] - vertex[0]) + : (float)INT_MAX); + } + + if (DEBUG_CLIP_VTX) { + ErrorF("\nvtx number: %d, VTX and slope:\n", *num); + for (i = 0; i < *num; i++) { + ErrorF("(%d, %d):%f ", + vertex[2*i], vertex[2*i + 1], + tmp_vtx_slope[i]); + } + ErrorF("\n"); + } + + /* Sort the vertex by slope. */ + for (i = 0; i < *num - 1; i++) { + int j; + float tmp_slope; + for (j = 1; j < *num - i - 1; j++) { + if (tmp_vtx_slope[j] < tmp_vtx_slope[j + 1]) { + tmp_slope = tmp_vtx_slope[j]; + tmp_vtx_slope[j] = tmp_vtx_slope[j + 1]; + tmp_vtx_slope[j + 1] = tmp_slope; + tmp[0] = vertex[2*j]; + tmp[1] = vertex[2*j + 1]; + vertex[2*j] = vertex[2*(j+1)]; + vertex[2*j + 1] = vertex[2*(j+1) + 1]; + vertex[2*(j+1)] = tmp[0]; + vertex[2*(j+1) + 1] = tmp[1]; + } + } + } + + if (DEBUG_CLIP_VTX) { + ErrorF("\nBefore return, vtx number: %d, VTX and slope:\n", *num); + for (i = 0; i < *num; i++) { + ErrorF("(%d, %d):%f ", + vertex[2*i], vertex[2*i + 1], + tmp_vtx_slope[i]); + } + ErrorF("\n"); + } + + return TRUE; +} + +static Bool +_glamor_trapezoids_with_shader(CARD8 op, + PicturePtr src, PicturePtr dst, + PictFormatPtr mask_format, INT16 x_src, INT16 y_src, + int ntrap, xTrapezoid * traps) +{ + ScreenPtr screen = dst->pDrawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + struct shader_key key; + PictFormatShort saved_source_format = 0; + PixmapPtr source_pixmap = NULL; + PixmapPtr dest_pixmap = NULL; + glamor_pixmap_private *source_pixmap_priv = NULL; + glamor_pixmap_private *dest_pixmap_priv = NULL; + glamor_pixmap_private *temp_src_priv = NULL; + int x_temp_src, y_temp_src; + int src_width, src_height; + int source_x_off, source_y_off; + GLfloat src_xscale = 1, src_yscale = 1; + int x_dst, y_dst; + int dest_x_off, dest_y_off; + GLfloat dst_xscale, dst_yscale; + BoxRec bounds; + PicturePtr temp_src = src; + glamor_gl_dispatch *dispatch = NULL; + int vert_stride = 3; + int ntriangle_per_loop; + int nclip_rect; + int mclip_rect; + int clip_processed; + int clipped_vtx[6*2]; + RegionRec region; + BoxPtr box = NULL; + BoxPtr pbox = NULL; + int traps_count = 0; + int traps_not_completed = 0; + xTrapezoid * ptrap = NULL; + int nbox; + float src_matrix[9]; + Bool ret = FALSE; + + /* 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 TRUE; + } + + miTrapezoidBounds(ntrap, traps, &bounds); + DEBUGF("The bounds for all traps is: bounds.x1 = %d, bounds.x2 = %d, " + "bounds.y1 = %d, bounds.y2 = %d\n", bounds.x1, bounds.x2, + bounds.y1, bounds.y2); + + /* No area need to render. */ + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return TRUE; + + dest_pixmap = glamor_get_drawable_pixmap(dst->pDrawable); + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + /* Currently. Always fallback to cpu if destination is in CPU memory.*/ + ret = FALSE; + DEBUGF("dst pixmap has no FBO.\n"); + goto TRAPEZOID_OUT; + } + + if (src->pDrawable) { + source_pixmap = glamor_get_drawable_pixmap(src->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + temp_src_priv = source_pixmap_priv; + if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) { + ret = FALSE; + goto TRAPEZOID_OUT; + } + } + + x_dst = bounds.x1; + y_dst = bounds.y1; + + src_width = bounds.x2 - bounds.x1; + src_height = bounds.y2 - bounds.y1; + + x_temp_src = x_src + bounds.x1 - (traps[0].left.p1.x >> 16); + y_temp_src = y_src + bounds.y1 - (traps[0].left.p1.y >> 16); + + if ((!src->pDrawable && + (src->pSourcePict->type != SourcePictTypeSolidFill)) //1. The Gradient case. + /* 2. Has no fbo but can upload.*/ + || (src->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) + && ((src_width * src_height * 4 < + source_pixmap->drawable.width * source_pixmap->drawable.height) + || !glamor_check_fbo_size(glamor_priv, source_pixmap->drawable.width, + source_pixmap->drawable.height)))) { + temp_src = glamor_convert_gradient_picture(screen, src, + x_src, y_src, + src_width, src_height); + if (!temp_src) { + temp_src = src; + ret = FALSE; + DEBUGF("Convert gradient picture failed\n"); + goto TRAPEZOID_OUT; + } + temp_src_priv = glamor_get_pixmap_private((PixmapPtr)temp_src->pDrawable); + x_temp_src = y_temp_src = 0; + } + + x_dst += dst->pDrawable->x; + y_dst += dst->pDrawable->y; + if (temp_src->pDrawable) { + x_temp_src += temp_src->pDrawable->x; + y_temp_src += temp_src->pDrawable->y; + } + + if (!miComputeCompositeRegion(®ion, + temp_src, NULL, dst, + x_temp_src, y_temp_src, + 0, 0, + x_dst, y_dst, + src_width, src_height)) { + DEBUGF("All the regions are clipped out, do nothing\n"); + goto TRAPEZOID_OUT; + } + + box = REGION_RECTS(®ion); + nbox = REGION_NUM_RECTS(®ion); + pbox = box; + + ret = glamor_composite_choose_shader(op, temp_src, NULL, dst, + temp_src_priv, NULL, dest_pixmap_priv, + &key, &saved_source_format); + if (ret == FALSE) { + DEBUGF("can not set the shader program for composite\n"); + goto TRAPEZOID_RESET_GL; + } + + 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); + + dispatch = glamor_get_dispatch(glamor_priv); + + glamor_get_drawable_deltas(dst->pDrawable, dest_pixmap, + &dest_x_off, &dest_y_off); + + pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + + if (glamor_priv->has_source_coords) { + source_pixmap = glamor_get_drawable_pixmap(temp_src->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + glamor_get_drawable_deltas(temp_src->pDrawable, + source_pixmap, + &source_x_off, &source_y_off); + pixmap_priv_get_scale(source_pixmap_priv, + &src_xscale, &src_yscale); + glamor_picture_get_matrixf(temp_src, src_matrix); + vert_stride += 3; + } + + if (glamor_priv->has_mask_coords) { + DEBUGF("Should never have mask coords here!\n"); + ret = FALSE; + goto TRAPEZOID_RESET_GL; + } + + /* A trapezoid clip with a rectangle will at most generate a hexagon, + which can be devided into 4 triangles to render. */ + ntriangle_per_loop = (vert_stride * nbox * ntrap * 4) > GLAMOR_COMPOSITE_VBO_VERT_CNT ? + (GLAMOR_COMPOSITE_VBO_VERT_CNT / vert_stride) : nbox * ntrap * 4; + ntriangle_per_loop = (ntriangle_per_loop / 4) * 4; + + nclip_rect = nbox; + while (nclip_rect) { + mclip_rect = (nclip_rect * ntrap * 4) > ntriangle_per_loop ? + (ntriangle_per_loop / (4 * ntrap)) : nclip_rect; + + if (!mclip_rect) {/* Maybe too many traps. */ + mclip_rect = 1; + ptrap = traps; + traps_count = ntriangle_per_loop / 4; + traps_not_completed = ntrap - traps_count; + } else { + traps_count = ntrap; + ptrap = traps; + traps_not_completed = 0; + } + +NTRAPS_LOOP_AGAIN: + + glamor_setup_composite_vbo(screen, mclip_rect * traps_count * 4 * vert_stride); + clip_processed = mclip_rect; + + + while (mclip_rect--) { + while (traps_count--) { + int vtx_num; + int i; + float vertices[3*2], source_texcoords[3*2]; + + DEBUGF("In loop of render trapezoid, nclip_rect = %d, mclip_rect = %d, " + "clip_processed = %d, traps_count = %d, traps_not_completed = %d\n", + nclip_rect, mclip_rect, clip_processed, traps_count, traps_not_completed); + + if (_glamor_clip_trapezoid_vertex(ptrap, pbox, clipped_vtx, &vtx_num)) { + for (i = 0; i < vtx_num - 2; i++) { + int clipped_vtx_tmp[3*2]; + + clipped_vtx_tmp[0] = clipped_vtx[0]; + clipped_vtx_tmp[1] = clipped_vtx[1]; + clipped_vtx_tmp[2] = clipped_vtx[(i+1)*2]; + clipped_vtx_tmp[3] = clipped_vtx[(i+1)*2 + 1]; + clipped_vtx_tmp[4] = clipped_vtx[(i+2)*2]; + clipped_vtx_tmp[5] = clipped_vtx[(i+2)*2 + 1]; + glamor_set_normalize_tri_vcoords( + dst_xscale, dst_yscale, clipped_vtx_tmp, + glamor_priv->yInverted, vertices); + DEBUGF("vertices of triangle: (%f X %f), (%f X %f), " + "(%f X %f)\n", vertices[0], vertices[1], + vertices[2], vertices[3], vertices[4], vertices[5]); + + + if (key.source != SHADER_SOURCE_SOLID) { + if (src->transform) { + glamor_set_transformed_normalize_tri_tcoords( + source_pixmap_priv, + src_matrix, src_xscale, src_yscale, + clipped_vtx_tmp, + glamor_priv->yInverted, + source_texcoords); + } else { + glamor_set_normalize_tri_tcoords( + src_xscale, src_yscale, + clipped_vtx_tmp, + glamor_priv->yInverted, + source_texcoords); + } + + DEBUGF("source_texcoords of triangle: (%f X %f), " + "(%f X %f), (%f X %f)\n", + source_texcoords[0], source_texcoords[1], + source_texcoords[2], source_texcoords[3], + source_texcoords[4], source_texcoords[5]); + } + + glamor_emit_composite_triangle(screen, source_texcoords, + NULL, vertices); + } + } + + ptrap++; + } + + if (traps_not_completed) { /* one loop of ntraps not completed */ + mclip_rect = 1; + traps_count = traps_not_completed > (ntriangle_per_loop / 4) ? + (ntriangle_per_loop / 4) : traps_not_completed; + traps_not_completed -= traps_count; + glamor_flush_composite_triangles(screen); + goto NTRAPS_LOOP_AGAIN; + } + + pbox++; + } + + glamor_flush_composite_triangles(screen); + + nclip_rect -= clip_processed; + } + + ret = TRUE; + +TRAPEZOID_RESET_GL: + dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK); + dispatch->glDisable(GL_BLEND); +#ifndef GLAMOR_GLES2 + dispatch->glActiveTexture(GL_TEXTURE0); + dispatch->glDisable(GL_TEXTURE_2D); + dispatch->glActiveTexture(GL_TEXTURE1); + dispatch->glDisable(GL_TEXTURE_2D); +#endif + dispatch->glUseProgram(0); + +TRAPEZOID_OUT: + if (box) { + REGION_UNINIT(dst->pDrawable->pScreen, ®ion); + } + + if (temp_src != src) { + FreePicture(temp_src, 0); + } else { + if (saved_source_format) { + src->format = saved_source_format; + } + } + + if (dispatch) { + glamor_put_dispatch(glamor_priv); + } + + return ret; +} + void glamor_init_trapezoid_shader(ScreenPtr screen) { diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index dfe8e568f..51a5b0e99 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -349,6 +349,25 @@ DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \ } while(0) +#define glamor_set_transformed_normalize_tri_tcoords(priv, \ + matrix, \ + xscale, \ + yscale, \ + vtx, \ + yInverted, \ + texcoords) \ + do { \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords, (vtx)[0], (vtx)[1], \ + yInverted); \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords+2, (vtx)[2], (vtx)[3], \ + yInverted); \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords+4, (vtx)[4], (vtx)[5], \ + yInverted); \ + } while (0) + #define glamor_set_transformed_normalize_tcoords( priv, \ matrix, \ xscale, \ @@ -370,6 +389,26 @@ yInverted); \ } while (0) +#define glamor_set_normalize_tri_tcoords(xscale, \ + yscale, \ + vtx, \ + yInverted, \ + texcoords) \ + do { \ + _glamor_set_normalize_tpoint(xscale, yscale, \ + (vtx)[0], (vtx)[1], \ + texcoords, \ + yInverted); \ + _glamor_set_normalize_tpoint(xscale, yscale, \ + (vtx)[2], (vtx)[3], \ + texcoords+2, \ + yInverted); \ + _glamor_set_normalize_tpoint(xscale, yscale, \ + (vtx)[4], (vtx)[5], \ + texcoords+4, \ + yInverted); \ + } while (0) + #define glamor_set_repeat_transformed_normalize_tcoords( priv, \ repeat_type, \ matrix, \ @@ -520,6 +559,31 @@ (vertices)[7] = (vertices)[5]; \ } while(0) +#define glamor_set_normalize_one_vcoord(xscale, yscale, x, y, \ + yInverted, vertices) \ + do { \ + (vertices)[0] = v_from_x_coord_x(xscale, x); \ + if (yInverted) { \ + (vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \ + } else { \ + (vertices)[1] = v_from_x_coord_y(yscale, y); \ + } \ + } while(0) + +#define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx, \ + yInverted, vertices) \ + do { \ + glamor_set_normalize_one_vcoord(xscale, yscale, \ + (vtx)[0], (vtx)[1], \ + yInverted, vertices); \ + glamor_set_normalize_one_vcoord(xscale, yscale, \ + (vtx)[2], (vtx)[3], \ + yInverted, vertices+2); \ + glamor_set_normalize_one_vcoord(xscale, yscale, \ + (vtx)[4], (vtx)[5], \ + yInverted, vertices+4); \ + } while(0) + #define glamor_set_tcoords_tri_strip(width, height, x1, y1, x2, y2, \ yInverted, vertices) \ do { \ From 8f31aed48ca9412f8f5df9c3d47d938c7c90bccb Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 5 Jun 2012 03:21:03 +0800 Subject: [PATCH 394/462] Use the direct render path for A1 Because when mask depth is 1, there is no Anti-Alias at all, in this case, the directly render can work well and it is faseter. Signed-off-by: Junyan He --- glamor/glamor_priv.h | 2 +- glamor/glamor_trapezoid.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1b45a71fe..055077cc1 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -965,7 +965,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER -#define GLAMOR_TRAPEZOID_SHADER +//#define GLAMOR_TRAPEZOID_SHADER #endif #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #if 0 diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 030e49030..2d26d792d 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -1409,15 +1409,34 @@ _glamor_trapezoids(CARD8 op, stride = PixmapBytePad(width, mask_format->depth); #ifdef GLAMOR_TRAPEZOID_SHADER - picture = glamor_create_mask_picture(screen, dst, mask_format, - width, height, 1); - if (!picture) - return TRUE; + /* We seperate the render to two paths. + Some GL implemetation do not implement the Anti-Alias for triangles + and polygen's filling. So when the edge is not vertical or horizontal, + sawtooth will be obvious. The trapezoid is widely used to render wide + lines and circles. In these case, the line or circle will be divided + into a large number of small trapezoids to approximate it, so the sawtooth + at the edge will cause the result not be acceptable. + When the depth of the mask is 1, there is no Anti-Alias needed, so we + use the clip logic to generate the result directly(fast path). + When the depth is not 1, AA is needed and we use a shader to generate + a temp mask pixmap. + */ + if(mask_format->depth == 1) { + ret = _glamor_trapezoids_with_shader(op, src, dst, mask_format, + x_src, y_src, ntrap, traps); + if(ret) + return TRUE; + } else { + picture = glamor_create_mask_picture(screen, dst, mask_format, + width, height, 1); + if (!picture) + return TRUE; - ret = _glamor_generate_trapezoid_with_shader(screen, picture, traps, ntrap, &bounds); + ret = _glamor_generate_trapezoid_with_shader(screen, picture, traps, ntrap, &bounds); - if (!ret) - FreePicture(picture, 0); + if (!ret) + FreePicture(picture, 0); + } #endif if (!ret) { From b4a499b7db068117801770b7ab80416014822101 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 12 Jun 2012 18:21:10 +0800 Subject: [PATCH 395/462] trapezoid: Fallback to sw-rasterize for largepixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_trapezoid.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 2d26d792d..cc6a70689 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -524,7 +524,8 @@ _glamor_trapezoids_with_shader(CARD8 op, dest_pixmap = glamor_get_drawable_pixmap(dst->pDrawable); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv) + || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { /* Currently. Always fallback to cpu if destination is in CPU memory.*/ ret = FALSE; DEBUGF("dst pixmap has no FBO.\n"); @@ -535,7 +536,9 @@ _glamor_trapezoids_with_shader(CARD8 op, source_pixmap = glamor_get_drawable_pixmap(src->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); temp_src_priv = source_pixmap_priv; - if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) { + if (source_pixmap_priv + && (source_pixmap_priv->type == GLAMOR_DRM_ONLY + || source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)) { ret = FALSE; goto TRAPEZOID_OUT; } @@ -558,6 +561,11 @@ _glamor_trapezoids_with_shader(CARD8 op, source_pixmap->drawable.width * source_pixmap->drawable.height) || !glamor_check_fbo_size(glamor_priv, source_pixmap->drawable.width, source_pixmap->drawable.height)))) { + + if (!glamor_check_fbo_size(glamor_priv, src_width, src_height)) { + ret = FALSE; + goto TRAPEZOID_OUT; + } temp_src = glamor_convert_gradient_picture(screen, src, x_src, y_src, src_width, src_height); @@ -609,7 +617,7 @@ _glamor_trapezoids_with_shader(CARD8 op, glamor_get_drawable_deltas(dst->pDrawable, dest_pixmap, &dest_x_off, &dest_y_off); - pixmap_priv_get_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); + pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); if (glamor_priv->has_source_coords) { source_pixmap = glamor_get_drawable_pixmap(temp_src->pDrawable); @@ -1136,7 +1144,8 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, pixmap = glamor_get_drawable_pixmap(picture->pDrawable); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { /* should always have here. */ + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { /* should always have here. */ DEBUGF("GLAMOR_PIXMAP_PRIV_HAS_FBO check failed, fallback\n"); return FALSE; } From 016995334e6acfad41574a9270b716db98ec697f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 15 Jun 2012 08:43:37 +0800 Subject: [PATCH 396/462] copyarea: Cleanup the error handling logic. Should use ok rather than mixed ok or ret. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index bfd957af1..243c1f28a 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -398,8 +398,7 @@ _glamor_copy_n_to_n(DrawablePtr src, RegionRec region; ScreenPtr screen; int src_x_off, src_y_off, dst_x_off, dst_y_off; - Bool ret = FALSE; - int ok = TRUE; + Bool ok = TRUE; int force_clip = 0; if (nbox == 0) @@ -423,10 +422,11 @@ _glamor_copy_n_to_n(DrawablePtr src, if (gc) { if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - goto fail; + goto fall_back; dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, gc->alu)) { glamor_put_dispatch(glamor_priv); + ok = FALSE; goto fail; } glamor_put_dispatch(glamor_priv); @@ -499,8 +499,10 @@ _glamor_copy_n_to_n(DrawablePtr src, * it. It's a little hacky, but avoid extra copy. */ temp_source_pixmap = glamor_create_pixmap(src->pScreen, 0, 0, src->depth, 0); - if (!temp_source_pixmap) + if (!temp_source_pixmap) { + ok = FALSE; goto fail; + } src->pScreen->ModifyPixmapHeader(temp_source_pixmap, src_pixmap->drawable.width, src_pixmap->drawable.height, @@ -619,12 +621,12 @@ fall_back: } glamor_finish_access(dst, GLAMOR_ACCESS_RW); } - ret = TRUE; + ok = TRUE; done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); - return ret; + return ok; } RegionPtr From 8656ddbbe7a38e5cd15e6d006bba19778e34e9e9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 15 Jun 2012 08:46:24 +0800 Subject: [PATCH 397/462] glamor_glyphs: Before get upload to cache flush is needed. When we can't get a cache hit and have to evict one cache entry to upload new picture, we need to flush the previous buffer. Otherwise, we may get corrupt glyphs rendering result. This is the reason why user-font-proxy may fail sometimes. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 224 +++++++++++++++++++++++++---------------- 1 file changed, 138 insertions(+), 86 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index dd3b4c625..362e46f45 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -226,6 +226,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; PixmapPtr scratch; + BoxRec box; GCPtr gc; gc = GetScratchGC(pCachePixmap->drawable.depth, screen); @@ -236,54 +237,51 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, scratch = pGlyphPixmap; if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) { + scratch = glamor_create_pixmap(screen, glyph->info.width, glyph->info.height, pCachePixmap-> drawable.depth, 0); if (scratch) { - if (pGlyphPixmap->drawable.depth != - pCachePixmap->drawable.depth) { - PicturePtr picture; - int error; + PicturePtr picture; + int error; - picture = - CreatePicture(0, - &scratch->drawable, - PictureMatchFormat - (screen, - pCachePixmap-> - drawable.depth, - cache->picture->format), - 0, NULL, serverClient, - &error); - if (picture) { - ValidatePicture(picture); - glamor_composite(PictOpSrc, - pGlyphPicture, - NULL, picture, - 0, 0, 0, 0, 0, - 0, - glyph->info.width, - glyph->info.height); - FreePicture(picture, 0); - } - } else { - glamor_copy_area(&pGlyphPixmap->drawable, - &scratch->drawable, - gc, 0, 0, - glyph->info.width, - glyph->info.height, 0, 0); + picture = + CreatePicture(0, + &scratch->drawable, + PictureMatchFormat + (screen, + pCachePixmap-> + drawable.depth, + cache->picture->format), + 0, NULL, serverClient, + &error); + if (picture) { + ValidatePicture(picture); + glamor_composite(PictOpSrc, + pGlyphPicture, + NULL, picture, + 0, 0, 0, 0, 0, + 0, + glyph->info.width, + glyph->info.height); + FreePicture(picture, 0); } } else { scratch = pGlyphPixmap; } } - (*gc->ops->CopyArea)(&scratch->drawable, &pCachePixmap->drawable, gc, - 0, 0, glyph->info.width, glyph->info.height, x, - y); - + box.x1 = x; + box.y1 = y; + box.x2 = x + glyph->info.width; + box.y2 = y + glyph->info.height; + glamor_copy_n_to_n_nf(&scratch->drawable, + &pCachePixmap->drawable, NULL, + &box, 1, + -x, -y, + FALSE, FALSE, 0, NULL); if (scratch != pGlyphPixmap) screen->DestroyPixmap(scratch); @@ -550,11 +548,13 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, *out_y = priv->y; return cache->picture; } +typedef void (*glyphs_flush)(void * arg); static glamor_glyph_cache_result_t glamor_buffer_glyph(ScreenPtr screen, glamor_glyph_buffer_t * buffer, - GlyphPtr glyph, int x_glyph, int y_glyph) + GlyphPtr glyph, int x_glyph, int y_glyph, + glyphs_flush glyphs_flush, void *flush_arg) { glamor_screen_private *glamor_screen = glamor_get_screen_private(screen); @@ -573,11 +573,18 @@ glamor_buffer_glyph(ScreenPtr screen, &glamor_screen->glyphCaches[PICT_FORMAT_RGB (glyph_picture->format) != 0]; - if (buffer->source && buffer->source != cache->picture) - return GLAMOR_GLYPH_NEED_FLUSH; + if (buffer->source + && buffer->source != cache->picture + && glyphs_flush) { + (*glyphs_flush)(flush_arg); + glyphs_flush = NULL; + } - if (buffer->count == GLYPH_BUFFER_SIZE) - return GLAMOR_GLYPH_NEED_FLUSH; + if (buffer->count == GLYPH_BUFFER_SIZE + && glyphs_flush) { + (*glyphs_flush)(flush_arg); + glyphs_flush = NULL; + } priv = glamor_glyph_get_private(glyph); @@ -588,6 +595,8 @@ glamor_buffer_glyph(ScreenPtr screen, if (buffer->source == NULL) buffer->source = priv->cache->picture; } else { + if (glyphs_flush) + (*glyphs_flush)(flush_arg); source = glamor_glyph_cache(screen, glyph, &x, &y); if (source != NULL) { rect = &buffer->rects[buffer->count++]; @@ -597,8 +606,10 @@ glamor_buffer_glyph(ScreenPtr screen, buffer->source = source; } else { source = GlyphPicture(glyph)[screen->myNum]; - if (buffer->source && buffer->source != source) - return GLAMOR_GLYPH_NEED_FLUSH; + if (buffer->source + && buffer->source != source + && glyphs_flush) + (*glyphs_flush)(flush_arg); buffer->source = source; rect = &buffer->rects[buffer->count++]; @@ -617,16 +628,22 @@ glamor_buffer_glyph(ScreenPtr screen, return GLAMOR_GLYPH_SUCCESS; } +struct glyphs_flush_mask_arg { + PicturePtr mask; + glamor_glyph_buffer_t *buffer; +}; static void -glamor_glyphs_flush_mask(PicturePtr mask, glamor_glyph_buffer_t * buffer) +glamor_glyphs_flush_mask(struct glyphs_flush_mask_arg *arg) { #ifdef RENDER - glamor_composite_glyph_rects(PictOpAdd, buffer->source, NULL, mask, - buffer->count, buffer->rects); + glamor_composite_glyph_rects(PictOpAdd, arg->buffer->source, + NULL, arg->mask, + arg->buffer->count, + arg->buffer->rects); #endif - buffer->count = 0; - buffer->source = NULL; + arg->buffer->count = 0; + arg->buffer->source = NULL; } static void @@ -651,7 +668,7 @@ glamor_glyphs_via_mask(CARD8 op, XID component_alpha; glamor_glyph_buffer_t buffer; xRectangle fill_rect; - + struct glyphs_flush_mask_arg arg; GCPtr gc; glamor_glyph_extents(nlist, list, glyphs, &extents); @@ -704,18 +721,21 @@ glamor_glyphs_via_mask(CARD8 op, n = list->len; while (n--) { glyph = *glyphs++; - if (glyph->info.width > 0 - && glyph->info.height > 0 - && glamor_buffer_glyph(screen, &buffer, - glyph, x, - y) == - GLAMOR_GLYPH_NEED_FLUSH) { - - glamor_glyphs_flush_mask(mask, &buffer); + && glyph->info.height > 0) { + glyphs_flush flush_func; + if (buffer.count) { + arg.mask = mask; + arg.buffer = &buffer; + flush_func = (glyphs_flush)glamor_glyphs_flush_mask; + } + else + flush_func = NULL; glamor_buffer_glyph(screen, &buffer, - glyph, x, y); + glyph, x, y, + flush_func, + (void*)&arg); } x += glyph->info.xOff; @@ -724,8 +744,11 @@ glamor_glyphs_via_mask(CARD8 op, list++; } - if (buffer.count) - glamor_glyphs_flush_mask(mask, &buffer); + if (buffer.count) { + arg.mask = mask; + arg.buffer = &buffer; + glamor_glyphs_flush_mask(&arg); + } x = extents.x1; y = extents.y1; @@ -739,27 +762,36 @@ glamor_glyphs_via_mask(CARD8 op, screen->DestroyPixmap(mask_pixmap); } +struct glyphs_flush_dst_arg { + CARD8 op; + PicturePtr src; + PicturePtr dst; + glamor_glyph_buffer_t * buffer; + INT16 x_src; + INT16 y_src; + INT16 x_dst; + INT16 y_dst; +}; + static void -glamor_glyphs_flush_dst(CARD8 op, - PicturePtr src, - PicturePtr dst, - glamor_glyph_buffer_t * buffer, - INT16 x_src, INT16 y_src, INT16 x_dst, INT16 y_dst) +glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg * arg) { int i; - glamor_composite_rect_t *rect = &buffer->rects[0]; - for (i = 0; i < buffer->count; i++, rect++) { + glamor_composite_rect_t *rect = &arg->buffer->rects[0]; + for (i = 0; i < arg->buffer->count; i++, rect++) { rect->x_mask = rect->x_src; rect->y_mask = rect->y_src; - rect->x_src = x_src + rect->x_dst - x_dst; - rect->y_src = y_src + rect->y_dst - y_dst; + rect->x_src = arg->x_src + rect->x_dst - arg->x_dst; + rect->y_src = arg->y_src + rect->y_dst - arg->y_dst; } - glamor_composite_glyph_rects(op, src, buffer->source, dst, - buffer->count, &buffer->rects[0]); + glamor_composite_glyph_rects(arg->op, arg->src, + arg->buffer->source, arg->dst, + arg->buffer->count, + &arg->buffer->rects[0]); - buffer->count = 0; - buffer->source = NULL; + arg->buffer->count = 0; + arg->buffer->source = NULL; } static void @@ -776,6 +808,7 @@ glamor_glyphs_to_dst(CARD8 op, int n; GlyphPtr glyph; glamor_glyph_buffer_t buffer; + struct glyphs_flush_dst_arg arg; buffer.count = 0; buffer.source = NULL; @@ -787,17 +820,28 @@ glamor_glyphs_to_dst(CARD8 op, glyph = *glyphs++; if (glyph->info.width > 0 - && glyph->info.height > 0 - && glamor_buffer_glyph(screen, &buffer, - glyph, x, - y) == - GLAMOR_GLYPH_NEED_FLUSH) { - glamor_glyphs_flush_dst(op, src, dst, - &buffer, x_src, - y_src, x_dst, - y_dst); - glamor_buffer_glyph(screen, &buffer, - glyph, x, y); + && glyph->info.height > 0) { + glyphs_flush flush_func; + + if (buffer.count) { + arg.op = op; + arg.src = src; + arg.dst = dst; + arg.buffer = &buffer; + arg.x_src = x_src; + arg.y_src = y_src; + arg.x_dst = x_dst; + arg.y_dst = y_dst; + flush_func = (glyphs_flush)glamor_glyphs_flush_dst; + } else + flush_func = NULL; + + glamor_buffer_glyph(screen, + &buffer, + glyph, x, y, + flush_func, + (void*)&arg); + } x += glyph->info.xOff; @@ -806,9 +850,17 @@ glamor_glyphs_to_dst(CARD8 op, list++; } - if (buffer.count) - glamor_glyphs_flush_dst(op, src, dst, &buffer, - x_src, y_src, x_dst, y_dst); + if (buffer.count) { + arg.op = op; + arg.src = src; + arg.dst = dst; + arg.buffer = &buffer; + arg.x_src = x_src; + arg.y_src = y_src; + arg.x_dst = x_dst; + arg.y_dst = y_dst; + glamor_glyphs_flush_dst(&arg); + } } static Bool From c41d5c79e7d8772be38b77122817fb872f2d721d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 15 Jun 2012 09:03:42 +0800 Subject: [PATCH 398/462] glamor_emit_composite_vert: Optimize to don't do two times vert coping. We change some macros to put the vert to the vertex buffer directly when we cacluating it. This way, we can get about 4% performance gain. This commit also fixed one RepeatPad bug, when we RepeatPad a not eaxct size fbo. We need to calculate the edge. The edge should be 1.0 - half point, not 1.0. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 131 ++++++++++------------ glamor/glamor_tile.c | 2 +- glamor/glamor_utils.h | 242 ++++++++++++++++++++++++++++------------- 3 files changed, 227 insertions(+), 148 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index a228a22e6..e2059b1b4 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -82,20 +82,20 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, "uniform int mask_repeat_mode;\n"; const char *relocate_texture = GLAMOR_DEFAULT_PRECISION - "vec2 rel_tex_coord(vec2 texture, vec2 wh, int repeat) \n" + "vec2 rel_tex_coord(vec2 texture, vec4 wh, int repeat) \n" "{\n" " vec2 rel_tex; \n" - " rel_tex = texture * wh; \n" + " rel_tex = texture * wh.xy; \n" " if (repeat == RepeatNone)\n" " return rel_tex; \n" " else if (repeat == RepeatNormal) \n" - " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n" + " rel_tex = floor(rel_tex) + (fract(rel_tex) / wh.xy); \n" " else if(repeat == RepeatPad) { \n" - " if (rel_tex.x > 1.0) rel_tex.x = 1.0; \n" - " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n" - " if (rel_tex.y > 1.0) rel_tex.y = 1.0; \n" + " if (rel_tex.x >= 1.0) rel_tex.x = 1.0 - wh.z * wh.x / 2.; \n" + " else if(rel_tex.x < 0.0) rel_tex.x = 0.0; \n" + " if (rel_tex.y >= 1.0) rel_tex.y = 1.0 - wh.w * wh.y / 2.; \n" " else if(rel_tex.y < 0.0) rel_tex.y = 0.0; \n" - " rel_tex = rel_tex / wh; \n" + " rel_tex = rel_tex / wh.xy; \n" " } \n" " else if(repeat == RepeatReflect) {\n" " if ((1.0 - mod(abs(floor(rel_tex.x)), 2.0)) < 0.001)\n" @@ -112,14 +112,14 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, /* The texture and the pixmap size is not match eaxctly, so can't sample it directly. * rel_sampler will recalculate the texture coords.*/ const char *rel_sampler = - " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec2 wh, int repeat, int set_alpha)\n" + " vec4 rel_sampler(sampler2D tex_image, vec2 tex, vec4 wh, int repeat, int set_alpha)\n" "{\n" " tex = rel_tex_coord(tex, wh, repeat - RepeatFix);\n" " if (repeat == RepeatFix) {\n" - " if (!(tex.x >= 0.0 && tex.x <= 1.0 \n" - " && tex.y >= 0.0 && tex.y <= 1.0))\n" + " if (!(tex.x >= 0.0 && tex.x < 1.0 \n" + " && tex.y >= 0.0 && tex.y < 1.0))\n" " return vec4(0.0, 0.0, 0.0, set_alpha);\n" - " tex = (fract(tex) / wh);\n" + " tex = (fract(tex) / wh.xy);\n" " }\n" " if (set_alpha != 1)\n" " return texture2D(tex_image, tex);\n" @@ -135,7 +135,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" - "uniform vec2 source_wh;" + "uniform vec4 source_wh;" "vec4 get_source()\n" "{\n" " if (source_repeat_mode < RepeatFix)\n" @@ -147,7 +147,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, const char *source_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture;\n" "uniform sampler2D source_sampler;\n" - "uniform vec2 source_wh;\n" + "uniform vec4 source_wh;\n" "vec4 get_source()\n" "{\n" " if (source_repeat_mode < RepeatFix) \n" @@ -162,7 +162,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, const char *mask_alpha_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" - "uniform vec2 mask_wh;\n" + "uniform vec4 mask_wh;\n" "vec4 get_mask()\n" "{\n" " if (mask_repeat_mode < RepeatFix) \n" @@ -174,7 +174,7 @@ glamor_create_composite_fs(glamor_gl_dispatch * dispatch, const char *mask_pixmap_fetch = GLAMOR_DEFAULT_PRECISION "varying vec2 mask_texture;\n" "uniform sampler2D mask_sampler;\n" - "uniform vec2 mask_wh;\n" + "uniform vec4 mask_wh;\n" "vec4 get_mask()\n" "{\n" " if (mask_repeat_mode < RepeatFix) \n" @@ -538,7 +538,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; - float wh[2]; + float wh[4]; int repeat_type; dispatch = glamor_get_dispatch(glamor_priv); @@ -605,19 +605,20 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, /* XXX may be we can eaxctly check whether we need to touch * the out-of-box area then determine whether we need to fix. **/ - /*if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE)*/ { - if (repeat_type != RepeatNone) + if (repeat_type != RepeatNone) + repeat_type += RepeatFix; + else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (picture->transform + || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) repeat_type += RepeatFix; - else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 - || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - if (picture->transform - || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) - repeat_type += RepeatFix; - } - if (repeat_type >= RepeatFix) { - glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); - dispatch->glUniform2fv(wh_location, 1, wh); - } + } + if (repeat_type >= RepeatFix) { + glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); + if (wh[0] != 1.0 || wh[1] != 1.0) + dispatch->glUniform4fv(wh_location, 1, wh); + else + repeat_type -= RepeatFix; } dispatch->glUniform1i(repeat_location, repeat_type); glamor_put_dispatch(glamor_priv); @@ -751,7 +752,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) dispatch->glBufferData(GL_ARRAY_BUFFER, n_verts * sizeof(float) * 2, NULL, GL_DYNAMIC_DRAW); - glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); } dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); @@ -814,6 +815,8 @@ glamor_emit_composite_vert(ScreenPtr screen, glamor_priv->vbo_offset += glamor_priv->vb_stride; } + + static void glamor_flush_composite_rects(ScreenPtr screen) { @@ -840,22 +843,6 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } -static void -glamor_emit_composite_rect(ScreenPtr screen, - const float *src_coords, - const float *mask_coords, - const float *dst_coords) -{ - 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}, @@ -926,34 +913,35 @@ glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, float *matrix, float xscale, float yscale, int x1, int y1, int x2, int y2, - int yInverted, float *texcoords) + int yInverted, float *texcoords, + int stride) { if (!matrix && repeat_type == RepeatNone) - glamor_set_normalize_tcoords(priv, xscale, yscale, + glamor_set_normalize_tcoords_ext(priv, xscale, yscale, x1, y1, x2, y2, yInverted, - texcoords); + texcoords, stride); else if (matrix && repeat_type == RepeatNone) - glamor_set_transformed_normalize_tcoords(priv, matrix, xscale, + glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, yscale, x1, y1, x2, y2, yInverted, - texcoords); + texcoords, stride); else if (!matrix && repeat_type != RepeatNone) - glamor_set_repeat_normalize_tcoords(priv, repeat_type, + glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, xscale, yscale, x1, y1, x2, y2, yInverted, - texcoords); + texcoords, stride); else if (matrix && repeat_type != RepeatNone) - glamor_set_repeat_transformed_normalize_tcoords(priv, repeat_type, + glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type, matrix, xscale, yscale, x1, y1, x2, y2, yInverted, - texcoords); + texcoords, stride); } Bool glamor_composite_choose_shader(CARD8 op, @@ -1251,7 +1239,7 @@ glamor_composite_with_shader(CARD8 op, GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; struct shader_key key; - float vertices[8], source_texcoords[8], mask_texcoords[8]; + float *vertices; int dest_x_off, dest_y_off; int source_x_off, source_y_off; int mask_x_off, mask_y_off; @@ -1316,11 +1304,12 @@ glamor_composite_with_shader(CARD8 op, while(nrect) { int mrect, rect_processed; + int vb_stride; mrect = nrect > nrect_max ? nrect_max : nrect ; glamor_setup_composite_vbo(screen, mrect * vert_stride); rect_processed = mrect; - + vb_stride = glamor_priv->vb_stride/sizeof(float); while (mrect--) { INT16 x_source; INT16 y_source; @@ -1342,33 +1331,34 @@ glamor_composite_with_shader(CARD8 op, DEBUGF("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", x_dest, y_dest, x_source, y_source,x_mask,y_mask,width,height); - - glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale, + vertices = (float*)(glamor_priv->vb + glamor_priv->vbo_offset); + assert(glamor_priv->vbo_offset < glamor_priv->vbo_size - glamor_priv->vb_stride); + glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale, dst_yscale, x_dest, y_dest, x_dest + width, y_dest + height, glamor_priv->yInverted, - vertices); - - if (key.source != SHADER_SOURCE_SOLID) + vertices, vb_stride); + vertices += 2; + if (key.source != SHADER_SOURCE_SOLID) { glamor_set_normalize_tcoords_generic( source_pixmap_priv, source->repeatType, psrc_matrix, src_xscale, src_yscale, x_source, y_source, x_source + width, y_source + height, - glamor_priv->yInverted, source_texcoords); + glamor_priv->yInverted, vertices, vb_stride); + vertices += 2; + } if (key.mask != SHADER_MASK_NONE - && key.mask != SHADER_MASK_SOLID) + && key.mask != SHADER_MASK_SOLID) { glamor_set_normalize_tcoords_generic( mask_pixmap_priv, mask->repeatType, pmask_matrix, mask_xscale, mask_yscale, x_mask, y_mask, x_mask + width, y_mask + height, - glamor_priv->yInverted, mask_texcoords); - - glamor_emit_composite_rect(screen, - source_texcoords, - mask_texcoords, - vertices); + glamor_priv->yInverted, vertices, vb_stride); + } + glamor_priv->render_nr_verts += 4; + glamor_priv->vbo_offset += glamor_priv->vb_stride * 4; rects++; } glamor_flush_composite_rects(screen); @@ -1500,6 +1490,7 @@ glamor_composite_clipped_region(CARD8 op, y_temp_src = y_source; x_temp_mask = x_mask; y_temp_mask = y_mask; + DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); @@ -1929,7 +1920,6 @@ glamor_composite_glyph_rects(CARD8 op, ValidatePicture(src); ValidatePicture(dst); - if (!(glamor_is_large_picture(src) || (mask && glamor_is_large_picture(mask)) || glamor_is_large_picture(dst))) { @@ -1946,7 +1936,6 @@ glamor_composite_glyph_rects(CARD8 op, mask_pixmap_priv, dst_pixmap_priv, nrect, rects)) return; } - n = nrect; r = rects; diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 206485ff2..7809e8bf8 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -124,7 +124,7 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile, GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; - float wh[2]; + float wh[4]; src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 51a5b0e99..4d8663637 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -74,6 +74,8 @@ PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, actual_w, actual_h); \ wh[0] = (float)priv->base.fbo->width / actual_w; \ wh[1] = (float)priv->base.fbo->height / actual_h; \ + wh[2] = 1.0 / priv->base.fbo->width; \ + wh[3] = 1.0 / priv->base.fbo->height; \ } while(0) #define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \ @@ -245,16 +247,11 @@ ty1 = d - priv->box.y1; \ ty2 = ty1 + ((_y2_) - (_y1_)); \ } \ - } else if (repeat_type == RepeatNormal) { \ + } else { /* RepeatNormal*/ \ tx1 = (c - priv->box.x1); \ ty1 = (d - priv->box.y1); \ tx2 = tx1 + ((_x2_) - (_x1_)); \ ty2 = ty1 + ((_y2_) - (_y1_)); \ - } else { \ - tx1 = _x1_ - priv->box.x1; \ - ty1 = _y1_ - priv->box.y1; \ - tx2 = tx1 + ((_x2_) - (_x1_)); \ - ty2 = ty1 + ((_y2_) - (_y1_)); \ } \ } while(0) @@ -368,6 +365,28 @@ yInverted); \ } while (0) +#define glamor_set_transformed_normalize_tcoords_ext( priv, \ + matrix, \ + xscale, \ + yscale, \ + tx1, ty1, tx2, ty2, \ + yInverted, texcoords, \ + stride) \ + do { \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords, tx1, ty1, \ + yInverted); \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords + 1 * stride, tx2, ty1, \ + yInverted); \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords + 2 * stride, tx2, ty2, \ + yInverted); \ + glamor_set_transformed_point(priv, matrix, xscale, yscale, \ + texcoords + 3 * stride, tx1, ty2, \ + yInverted); \ + } while (0) + #define glamor_set_transformed_normalize_tcoords( priv, \ matrix, \ xscale, \ @@ -375,20 +394,17 @@ tx1, ty1, tx2, ty2, \ yInverted, texcoords) \ do { \ - glamor_set_transformed_point(priv, matrix, xscale, yscale, \ - texcoords, tx1, ty1, \ - yInverted); \ - glamor_set_transformed_point(priv, matrix, xscale, yscale, \ - texcoords + 2, tx2, ty1, \ - yInverted); \ - glamor_set_transformed_point(priv, matrix, xscale, yscale, \ - texcoords + 4, tx2, ty2, \ - yInverted); \ - glamor_set_transformed_point(priv, matrix, xscale, yscale, \ - texcoords + 6, tx1, ty2, \ - yInverted); \ + glamor_set_transformed_normalize_tcoords_ext( priv, \ + matrix, \ + xscale, \ + yscale, \ + tx1, ty1, tx2, ty2, \ + yInverted, texcoords, \ + 2); \ } while (0) + + #define glamor_set_normalize_tri_tcoords(xscale, \ yscale, \ vtx, \ @@ -409,7 +425,7 @@ yInverted); \ } while (0) -#define glamor_set_repeat_transformed_normalize_tcoords( priv, \ +#define glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \ repeat_type, \ matrix, \ xscale, \ @@ -417,13 +433,14 @@ _x1_, _y1_, \ _x2_, _y2_, \ yInverted, \ - texcoords) \ + texcoords, \ + stride) \ do { \ if (priv->type != GLAMOR_TEXTURE_LARGE) { \ - glamor_set_transformed_normalize_tcoords(priv, matrix, xscale, \ + glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \ yscale, _x1_, _y1_, \ _x2_, _y2_, yInverted, \ - texcoords); \ + texcoords, stride); \ } else { \ /* For a large pixmap, if both transform and repeat are set, * the transform must only has x and y scale factor.*/ \ @@ -453,54 +470,115 @@ _glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1, \ texcoords, yInverted); \ _glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2, \ - texcoords + 2, yInverted); \ + texcoords + 1 * stride, yInverted); \ _glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3, \ - texcoords + 4, yInverted); \ + texcoords + 2 * stride, yInverted); \ _glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4, \ - texcoords + 6, yInverted); \ + texcoords + 3 * stride, yInverted); \ } \ } while (0) + +#define glamor_set_repeat_transformed_normalize_tcoords( priv, \ + repeat_type, \ + matrix, \ + xscale, \ + yscale, \ + _x1_, _y1_, \ + _x2_, _y2_, \ + yInverted, \ + texcoords) \ + do { \ + glamor_set_repeat_transformed_normalize_tcoords_ext( priv, \ + repeat_type, \ + matrix, \ + xscale, \ + yscale, \ + _x1_, _y1_, \ + _x2_, _y2_, \ + yInverted, \ + texcoords, \ + 2); \ + } while (0) + #define _glamor_set_normalize_tcoords(xscale, yscale, tx1, \ ty1, tx2, ty2, \ - yInverted, vertices) \ + yInverted, vertices, stride) \ do { \ - (vertices)[0] = t_from_x_coord_x(xscale, tx1); \ - (vertices)[2] = t_from_x_coord_x(xscale, tx2); \ - (vertices)[4] = (vertices)[2]; \ - (vertices)[6] = (vertices)[0]; \ + /* vertices may be write-only, so we use following \ + * temporary variable. */ \ + float _t0_, _t1_, _t2_, _t5_; \ + (vertices)[0] = _t0_ = t_from_x_coord_x(xscale, tx1); \ + (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \ + (vertices)[2 * stride] = _t2_; \ + (vertices)[3 * stride] = _t0_; \ if (yInverted) { \ - (vertices)[1] = t_from_x_coord_y_inverted(yscale, ty1); \ - (vertices)[5] = t_from_x_coord_y_inverted(yscale, ty2); \ + (vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \ + (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2);\ } \ else { \ - (vertices)[1] = t_from_x_coord_y(yscale, ty1); \ - (vertices)[5] = t_from_x_coord_y(yscale, ty2); \ + (vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1); \ + (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2);\ } \ - (vertices)[3] = (vertices)[1]; \ - (vertices)[7] = (vertices)[5]; \ - DEBUGF("texture %f %f %f %f\n", tx1, ty1, tx2, ty2); \ - DEBUGF("texture %f %f %f %f\n", (vertices)[0], (vertices)[1], \ - (vertices)[2], (vertices)[3]); \ - DEBUGF("texture %f %f %f %f\n", (vertices)[4], (vertices)[5], \ - (vertices)[6], (vertices)[7]); \ + (vertices)[1 * stride + 1] = _t1_; \ + (vertices)[3 * stride + 1] = _t5_; \ } while(0) +#define glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices, stride) \ + do { \ + if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + float tx1, tx2, ty1, ty2; \ + int fbo_x_off, fbo_y_off; \ + pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ + tx1 = x1 + fbo_x_off; \ + tx2 = x2 + fbo_x_off; \ + ty1 = y1 + fbo_y_off; \ + ty2 = y2 + fbo_y_off; \ + _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ + tx2, ty2, yInverted, vertices, \ + stride); \ + } else \ + _glamor_set_normalize_tcoords(xscale, yscale, x1, y1, \ + x2, y2, yInverted, vertices, stride);\ + } while(0) + + #define glamor_set_normalize_tcoords(priv, xscale, yscale, \ x1, y1, x2, y2, \ yInverted, vertices) \ do { \ - float tx1, tx2, ty1, ty2; \ - int fbo_x_off, fbo_y_off; \ - pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ - tx1 = x1 + fbo_x_off; \ - tx2 = x2 + fbo_x_off; \ - ty1 = y1 + fbo_y_off; \ - ty2 = y2 + fbo_y_off; \ - _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ - tx2, ty2, yInverted, vertices); \ + glamor_set_normalize_tcoords_ext(priv, xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices, 2); \ } while(0) +#define glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \ + xscale, yscale, \ + _x1_, _y1_, _x2_, _y2_, \ + yInverted, vertices, stride)\ + do { \ + if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + float tx1, tx2, ty1, ty2; \ + if (repeat_type == RepeatPad) { \ + tx1 = _x1_ - priv->large.box.x1; \ + ty1 = _y1_ - priv->large.box.y1; \ + tx2 = tx1 + ((_x2_) - (_x1_)); \ + ty2 = ty1 + ((_y2_) - (_y1_)); \ + } else { \ + glamor_get_repeat_coords((&priv->large), repeat_type, \ + tx1, ty1, tx2, ty2, \ + _x1_, _y1_, _x2_, _y2_); \ + } \ + _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ + tx2, ty2, yInverted, vertices, \ + stride); \ + } else \ + _glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_, \ + _x2_, _y2_, yInverted, vertices, \ + stride); \ + } while(0) #define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \ @@ -508,16 +586,10 @@ _x1_, _y1_, _x2_, _y2_, \ yInverted, vertices) \ do { \ - float tx1, tx2, ty1, ty2; \ - if (priv->type == GLAMOR_TEXTURE_LARGE) \ - glamor_get_repeat_coords((&priv->large), repeat_type, \ - tx1, ty1, tx2, ty2, \ - _x1_, _y1_, _x2_, _y2_); \ - else { \ - tx1 = _x1_; tx2 = _x2_; ty1 = _y1_; ty2 = _y2_; \ - } \ - _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ - tx2, ty2, yInverted, vertices); \ + glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type, \ + xscale, yscale, \ + _x1_, _y1_, _x2_, _y2_, \ + yInverted, vertices, 2); \ } while(0) #define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale, \ @@ -603,26 +675,44 @@ (vertices)[5] = (vertices)[7]; \ } while(0) +#define glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices, stride) \ + do { \ + int fbo_x_off, fbo_y_off; \ + /* vertices may be write-only, so we use following \ + * temporary variable. */ \ + float _t0_, _t1_, _t2_, _t5_; \ + pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ + (vertices)[0] = _t0_ = v_from_x_coord_x(xscale, x1 + fbo_x_off); \ + (vertices)[1 * stride] = _t2_ = v_from_x_coord_x(xscale, \ + x2 + fbo_x_off); \ + (vertices)[2 * stride] = _t2_; \ + (vertices)[3 * stride] = _t0_; \ + if (yInverted) { \ + (vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \ + y1 + fbo_y_off); \ + (vertices)[2 * stride + 1] = _t5_ = \ + v_from_x_coord_y_inverted(yscale, \ + y2 + fbo_y_off); \ + } \ + else { \ + (vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off); \ + (vertices)[2 * stride + 1] = _t5_ = v_from_x_coord_y(yscale, \ + y2 + fbo_y_off); \ + } \ + (vertices)[1 * stride + 1] = _t1_; \ + (vertices)[3 * stride + 1] = _t5_; \ + } while(0) + + #define glamor_set_normalize_vcoords(priv, xscale, yscale, \ x1, y1, x2, y2, \ yInverted, vertices) \ do { \ - int fbo_x_off, fbo_y_off; \ - pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ - (vertices)[0] = v_from_x_coord_x(xscale, x1 + fbo_x_off); \ - (vertices)[2] = v_from_x_coord_x(xscale, x2 + fbo_x_off); \ - (vertices)[4] = (vertices)[2]; \ - (vertices)[6] = (vertices)[0]; \ - if (yInverted) { \ - (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1 + fbo_y_off);\ - (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2 + fbo_y_off);\ - } \ - else { \ - (vertices)[1] = v_from_x_coord_y(yscale, y1 + fbo_y_off); \ - (vertices)[5] = v_from_x_coord_y(yscale, y2 + fbo_y_off); \ - } \ - (vertices)[3] = (vertices)[1]; \ - (vertices)[7] = (vertices)[5]; \ + glamor_set_normalize_vcoords_ext(priv, xscale, yscale, \ + x1, y1, x2, y2, \ + yInverted, vertices, 2); \ } while(0) #define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \ From 6ed418d17b5143f32b3b415103f3157a1b05e3db Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 15 Jun 2012 13:31:30 +0800 Subject: [PATCH 399/462] gles2_largepixmap: force clip for a non-large pixmap. One case we need force clip when download/upload a drm_texture pixmap. Actually, this is only meaningful for testing purpose. As we may set the max_fbo_size to a very small value, but the drm texture may exceed this value but the drm texture pixmap is not largepixmap. This is not a problem with OpenGL. But for GLES2, we may need to call glamor_es2_pixmap_read_prepare to create a temporary fbo to do the color conversion. Then we have to force clip the drm pixmap here to avoid large pixmap handling at glamor_es2_pixmap_read_prepare. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 30 +++++++++++++++++++++++++----- glamor/glamor_render.c | 10 +++++++--- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 10d6df396..ce243abcf 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -684,6 +684,7 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h GLenum format, type; int no_alpha, revert, swap_rb; glamor_pixmap_private *pixmap_priv; + Bool force_clip; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, @@ -699,7 +700,10 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h return FALSE; pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP + && !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h); + + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) { RegionRec region; BoxRec box; int n_region; @@ -715,7 +719,12 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h box.x2 = x + w; box.y2 = y + h; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); + if (!force_clip) + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); + else + clipped_regions = glamor_compute_clipped_regions_ext(pixmap_priv, ®ion, &n_region, + pixmap_priv->base.glamor_priv->max_fbo_size, + pixmap_priv->base.glamor_priv->max_fbo_size, 0, 0); DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap); for(i = 0; i < n_region; i++) { @@ -1058,13 +1067,14 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, GLenum format, type; int no_alpha, revert, swap_rb; glamor_pixmap_private *pixmap_priv; + Bool force_clip; if (glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, &no_alpha, &revert, - &swap_rb, 1)) { + &swap_rb, 0)) { glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); return NULL; @@ -1074,7 +1084,10 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return NULL; - if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP + && !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h); + + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) { RegionRec region; BoxRec box; @@ -1091,7 +1104,14 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, box.x2 = x + w; box.y2 = y + h; RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); + + if (!force_clip) + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); + else + clipped_regions = glamor_compute_clipped_regions_ext(pixmap_priv, ®ion, &n_region, + pixmap_priv->base.glamor_priv->max_fbo_size, + pixmap_priv->base.glamor_priv->max_fbo_size, 0, 0); + DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h); for(i = 0; i < n_region; i++) { diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e2059b1b4..6f83c4dd2 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -602,8 +602,10 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - /* XXX may be we can eaxctly check whether we need to touch - * the out-of-box area then determine whether we need to fix. + + /* + * GLES2 doesn't support RepeatNone. We need to fix it anyway. + * **/ if (repeat_type != RepeatNone) repeat_type += RepeatFix; @@ -615,7 +617,9 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, } if (repeat_type >= RepeatFix) { glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); - if (wh[0] != 1.0 || wh[1] != 1.0) + if ((wh[0] != 1.0 || wh[1] != 1.0 ) + || (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + && repeat_type == RepeatFix)) dispatch->glUniform4fv(wh_location, 1, wh); else repeat_type -= RepeatFix; From 2122e60bf9027b63ddc59c0aa2a441af3687cb3a Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 15 Jun 2012 09:00:15 +0800 Subject: [PATCH 400/462] Fix a bug for trapezoid clip We find in some cases the trapezoid will be render as a triangle and the left edge and right edge will cross with each other just bellow the top or over the bottom. The distance between the cross poind and the top or bottom is less than pixman_fixed_1_minus_e, so after the fixed converted to int, the cross point has the same value with the top or botton and the triangle should not be affected. But in our clip logic, the cross point will be clipped out. So add a logic to fix this problem. Signed-off-by: Junyan He --- glamor/glamor_trapezoid.c | 115 +++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 8 deletions(-) diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index cc6a70689..3ad9e5007 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -38,12 +38,36 @@ #ifdef GLAMOR_TRAPEZOID_SHADER +#define DEBUG_CLIP_VTX 0 + #define POINT_INSIDE_CLIP_RECT(point, rect) \ (point[0] >= IntToxFixed(rect->x1) \ && point[0] <= IntToxFixed(rect->x2) \ && point[1] >= IntToxFixed(rect->y1) \ && point[1] <= IntToxFixed(rect->y2)) +static xFixed +_glamor_lines_crossfixedY (xLineFixed *l, xLineFixed *r) +{ + xFixed dx1 = l->p2.x - l->p1.x; + xFixed dx2 = r->p2.x - r->p1.x; + xFixed dy1 = l->p2.y - l->p1.y; + xFixed dy2 = r->p2.y - r->p1.y; + xFixed_32_32 tmp = (xFixed_32_32) dy2 * dy1; + xFixed_32_32 dividend1 = (tmp >> 32) * (l->p1.x - r->p1.x); + tmp = (xFixed_32_32) dx1 * dy2; + xFixed_32_32 dividend2 = (tmp >> 32) * l->p1.y; + tmp = (xFixed_32_32) dy1 * dx2; + xFixed_32_32 dividend3 = (tmp >> 32) * r->p1.y; + xFixed_32_32 divisor = ((xFixed_32_32) dx1 * (xFixed_32_32) dy2 + - (xFixed_32_32) dy1 * (xFixed_32_32) dx2) >> 32; + + if (divisor) + return (xFixed)((dividend2 - dividend1 - dividend3) / divisor); + + return 0xFFFFFFFF; +} + static xFixed _glamor_linefixedX (xLineFixed *l, xFixed y, Bool ceil) { @@ -67,22 +91,86 @@ _glamor_linefixedY (xLineFixed *l, xFixed x, Bool ceil) } static Bool -point_inside_trapezoid(int point[2], xTrapezoid * trap) +point_inside_trapezoid(int point[2], xTrapezoid * trap, xFixed cut_y) { int ret = TRUE; int tmp; - if (point[1] > trap->bottom - || point[1] < trap->top) + if (point[1] > trap->bottom) { ret = FALSE; + if (DEBUG_CLIP_VTX) { + ErrorF("Out of Trap bottom, point[1] = %d(0x%x)), " + "bottom = %d(0x%x)\n", + (unsigned int)xFixedToInt(point[1]), point[1], + (unsigned int)xFixedToInt(trap->bottom), + (unsigned int)trap->bottom); + } + + return ret; + } + + if (point[1] < trap->top) { + ret = FALSE; + if (DEBUG_CLIP_VTX) { + ErrorF("Out of Trap top, point[1] = %d(0x%x)), " + "top = %d(0x%x)\n", + (unsigned int)xFixedToInt(point[1]), point[1], + (unsigned int)xFixedToInt(trap->top), + (unsigned int)trap->top); + } + + return ret; + } tmp = _glamor_linefixedX (&trap->left, point[1], FALSE); - if (point[0] < tmp) + if (point[0] < tmp) { ret = FALSE; + if (abs(cut_y - trap->top) < pixman_fixed_1_minus_e && + abs(point[1] - trap->top) < pixman_fixed_1_minus_e && + tmp - point[0] < pixman_fixed_1_minus_e) { + ret = TRUE; + } else if (abs(cut_y - trap->bottom) < pixman_fixed_1_minus_e && + point[1] - trap->bottom < pixman_fixed_1_minus_e && + tmp - point[0] < pixman_fixed_1_minus_e) { + ret = TRUE; + } + + if (DEBUG_CLIP_VTX && !ret) { + ErrorF("Out of Trap left, point[0] = %d(0x%x)), " + "left = %d(0x%x)\n", + (unsigned int)xFixedToInt(point[0]), point[0], + (unsigned int)xFixedToInt(tmp), (unsigned int)tmp); + } + + if (!ret) + return ret; + } + tmp = _glamor_linefixedX (&trap->right, point[1], TRUE); - if (point[0] > tmp) + if (point[0] > tmp) { ret = FALSE; + if (abs(cut_y - trap->top) < pixman_fixed_1_minus_e && + abs(point[1] - trap->top) < pixman_fixed_1_minus_e && + point[0] - tmp < pixman_fixed_1_minus_e) { + ret = TRUE; + } else if (abs(cut_y - trap->bottom) < pixman_fixed_1_minus_e && + abs(point[1] - trap->bottom) < pixman_fixed_1_minus_e && + point[0] - tmp < pixman_fixed_1_minus_e) { + ret = TRUE; + } + + if (DEBUG_CLIP_VTX && !ret) { + ErrorF("Out of Trap right, point[0] = %d(0x%x)), " + "right = %d(0x%x)\n", + (unsigned int)xFixedToInt(point[0]), point[0], + (unsigned int)xFixedToInt(tmp), (unsigned int)tmp); + } + + if (!ret) + return ret; + } + return ret; } @@ -125,12 +213,11 @@ glamor_flush_composite_triangles(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } -#define DEBUG_CLIP_VTX 0 - static Bool _glamor_clip_trapezoid_vertex(xTrapezoid * trap, BoxPtr pbox, int vertex[6], int *num) { + xFixed edge_cross_y = 0xFFFFFFFF; int tl[2]; int bl[2]; int tr[2]; @@ -217,7 +304,7 @@ _glamor_clip_trapezoid_vertex(xTrapezoid * trap, BoxPtr pbox, #define ADD_VERTEX_IF_INSIDE(vtx) \ if(POINT_INSIDE_CLIP_RECT(vtx, pbox) \ - && point_inside_trapezoid(vtx, trap)){ \ + && point_inside_trapezoid(vtx, trap, edge_cross_y)){ \ tmp_vtx[vertex_num] = xFixedToInt(vtx[0]); \ tmp_vtx[vertex_num + 1] = xFixedToInt(vtx[1]); \ vertex_num += 2; \ @@ -239,6 +326,18 @@ _glamor_clip_trapezoid_vertex(xTrapezoid * trap, BoxPtr pbox, "the Rect\n"); \ } + /*Trap's right edge cut right edge. */ + if((!IS_TRAP_EDGE_VERTICAL((&trap->left))) || + (!IS_TRAP_EDGE_VERTICAL((&trap->right)))) { + edge_cross_y = _glamor_lines_crossfixedY((&trap->left), (&trap->right)); + if (DEBUG_CLIP_VTX) { + ErrorF("Trap's left edge cut right edge at %d(0x%x), " + "trap_top = %x, trap_bottom = %x\n", + xFixedToInt(edge_cross_y), edge_cross_y, + (unsigned int)trap->top, (unsigned int)trap->bottom); + } + } + /*Trap's TopLeft, BottomLeft, TopRight and BottomRight. */ CACULATE_CUT_VERTEX(tl, 1, FALSE, trap->top, (&trap->left)); CACULATE_CUT_VERTEX(bl, 1, FALSE, trap->bottom, (&trap->left)); From 1e4fc85a71cc6498a7e11872026062fceb5bbdf1 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 21 Jun 2012 19:26:28 +0800 Subject: [PATCH 401/462] glamor_fbo: fix a memory leak for large pixmap. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 1ab76868d..d3b9009ce 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -553,8 +553,9 @@ glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv) fbo = glamor_pixmap_detach_fbo(priv); if (fbo) glamor_destroy_fbo(fbo); - free(priv); } + + free(priv); } Bool From 7acbe895618837305cf4050731ccd1cd3bc11589 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 21 Jun 2012 19:27:07 +0800 Subject: [PATCH 402/462] glamor_create_pixmap: Allocate glyphs pixmap in memory. As we have glyphs atlas cache, we don't need to hold each glyphs on GPU. And for the subsequent optimization, we need to store the original glyphs pixmap on system memory. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/glamor.c b/glamor/glamor.c index e4917836d..d087b8275 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -142,6 +142,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; if ((usage == GLAMOR_CREATE_PIXMAP_CPU + || usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE || (w == 0 && h == 0) || !glamor_check_pixmap_fbo_depth(depth)) || (!GLAMOR_TEXTURED_LARGE_PIXMAP && From ea4c22716ca1544e924c7462db6a2797afebff59 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 21 Jun 2012 19:29:06 +0800 Subject: [PATCH 403/462] glamor_render: Don't fallback when rendering glyphs with OpOver. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6f83c4dd2..b33d96996 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -996,7 +996,8 @@ Bool glamor_composite_choose_shader(CARD8 op, &source_solid_color[2], &source_solid_color[3], PICT_a8r8g8b8); - } + } else + goto fail; } else { key.source = SHADER_SOURCE_TEXTURE_ALPHA; } @@ -1012,7 +1013,8 @@ Bool glamor_composite_choose_shader(CARD8 op, &mask_solid_color[1], &mask_solid_color[2], &mask_solid_color[3], PICT_a8r8g8b8); - } + } else + goto fail; } else { key.mask = SHADER_MASK_TEXTURE_ALPHA; } @@ -1921,6 +1923,7 @@ glamor_composite_glyph_rects(CARD8 op, { int n; glamor_composite_rect_t *r; + Bool ok; ValidatePicture(src); ValidatePicture(dst); @@ -1936,10 +1939,29 @@ glamor_composite_glyph_rects(CARD8 op, mask_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(mask->pDrawable)); if (src->pDrawable) src_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(src->pDrawable)); - if (glamor_composite_with_shader(op, src, mask, dst, src_pixmap_priv, + + if (mask && mask->componentAlpha) { + if (op == PictOpOver) { + ok = glamor_composite_with_shader(PictOpOutReverse, + src, mask, dst, src_pixmap_priv, + mask_pixmap_priv, dst_pixmap_priv, nrect, rects); + if (!ok) + goto fallback; + ok |= glamor_composite_with_shader(PictOpAdd, + src, mask, dst, src_pixmap_priv, + mask_pixmap_priv, dst_pixmap_priv, nrect, rects); + if (ok) + return; + assert(0); + } + } else { + if (glamor_composite_with_shader(op, src, mask, dst, src_pixmap_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects)) return; + } } + +fallback: n = nrect; r = rects; From c1bd50d58d2c7b39e2b5c529bd86fde1ab14d8e6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 21 Jun 2012 19:30:51 +0800 Subject: [PATCH 404/462] glamor_glyphs: Detect fake or real glyphs overlap. To split a glyph's extent region to three sub-boxes as below. left box 2 x h center box (w-4) x h right box 2 x h Take a simple glyph A as an example: * __* *__ ***** * * ~~ ~~ The left box and right boxes are both 2 x 2. The center box is 2 x 4. The left box has two bitmaps 0001'b and 0010'b to indicate the real inked area. The right box also has two bitmaps 0010'b and 0001'b. And then we can check the inked area in left and right boxes with previous glyph. If the direction is from left to right, then we need to check the previous right bitmap with current left bitmap. And if we found the center box has overlapped or we overlap with not only the previous glyph, we will treat it as real overlapped and will render the glyphs via mask. If we only intersect with previous glyph on the left/right edge. Then we further compute the real overlapped bits. We set a loose check criteria here, if it has less than two pixel overlapping, we treat it as non-overlapping. With this patch, The aa10text boost fom 1660000 to 320000. Almost double the performance! And the cairo test result is the same as without this patch. Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 24 --- glamor/glamor_glyphs.c | 407 +++++++++++++++++++++++++++++++++-------- glamor/glamor_priv.h | 2 + glamor/glamor_utils.h | 24 +++ 4 files changed, 355 insertions(+), 102 deletions(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index d3b9009ce..4af831d54 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -51,30 +51,6 @@ &pos->member != (head); \ pos = tmp, tmp = __container_of(pos->member.prev, tmp, member)) -#ifdef __i386__ -static inline unsigned long __fls(unsigned long x) -{ - asm("bsr %1,%0" - : "=r" (x) - : "rm" (x)); - return x; -} -#else -static inline unsigned long __fls(unsigned long x) -{ - int n; - - if (x == 0) return(0); - n = 0; - if (x <= 0x0000FFFF) {n = n +16; x = x <<16;} - if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;} - if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;} - if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;} - if (x <= 0x7FFFFFFF) {n = n + 1;} - return 31 - n; -} -#endif - inline static int cache_wbucket(int size) { int order = __fls(size / 32); diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 362e46f45..fa8b55f15 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -33,7 +33,7 @@ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Owen Taylor @@ -69,7 +69,7 @@ typedef struct { PicturePtr source; - glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE]; + glamor_composite_rect_t rects[GLYPH_BUFFER_SIZE + 4]; int count; } glamor_glyph_buffer_t; @@ -77,6 +77,10 @@ struct glamor_glyph { glamor_glyph_cache_t *cache; uint16_t x, y; uint16_t size, pos; + unsigned long long left_x1_map, left_x2_map; + unsigned long long right_x1_map, right_x2_map; /* Use to check real pixel overlap or not. */ + Bool has_edge_map; + Bool cached; }; typedef enum { @@ -253,8 +257,8 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, PictureMatchFormat (screen, pCachePixmap-> - drawable.depth, - cache->picture->format), + drawable.depth, + cache->picture->format), 0, NULL, serverClient, &error); if (picture) { @@ -264,7 +268,7 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, NULL, picture, 0, 0, 0, 0, 0, 0, - glyph->info.width, + glyph->info.width, glyph->info.height); FreePicture(picture, 0); } @@ -299,7 +303,8 @@ glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph) if (priv == NULL) return; - priv->cache->glyphs[priv->pos] = NULL; + if (priv->cached) + priv->cache->glyphs[priv->pos] = NULL; glamor_glyph_set_private(glyph, NULL); free(priv); @@ -350,18 +355,101 @@ glamor_glyph_extents(int nlist, extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2; } +static void +glamor_glyph_priv_get_edge_map(GlyphPtr glyph, struct glamor_glyph *priv, + PicturePtr glyph_picture) +{ + PixmapPtr glyph_pixmap = (PixmapPtr) glyph_picture->pDrawable; + struct glamor_pixmap_private *pixmap_priv; + int j; + unsigned long long left_x1_map, left_x2_map, right_x1_map, right_x2_map; + int bitsPerPixel; + int stride; + void *bits; + int width; + unsigned int left_x1_data, left_x2_data, right_x1_data, right_x2_data; + + bitsPerPixel = glyph_pixmap->drawable.bitsPerPixel; + stride = glyph_pixmap->devKind; + bits = glyph_pixmap->devPrivate.ptr; + width = glyph->info.width; + pixmap_priv = glamor_get_pixmap_private(glyph_pixmap); + + if (glyph_pixmap->drawable.width < 2 + || !(glyph_pixmap->drawable.depth == 8 + || glyph_pixmap->drawable.depth == 1 + || glyph_pixmap->drawable.depth == 32)) { + priv->has_edge_map = FALSE; + return; + } + + left_x1_map = left_x2_map = 0; + right_x1_map = right_x2_map = 0; + + for(j = 0; j < glyph_pixmap->drawable.height; j++) + { + if (bitsPerPixel == 8) { + unsigned char *data; + data = (unsigned char*)((unsigned char*)bits + stride * j); + left_x1_data = *data++; + left_x2_data = *data; + data = (unsigned char*)((unsigned char*)bits + stride * j + width - 2); + right_x1_data = *data++; + right_x2_data = *data; + } else if (bitsPerPixel == 32) { + left_x1_data = *((unsigned int*)bits + stride/4 * j); + left_x2_data = *((unsigned int*)bits + stride/4 * j + 1); + right_x1_data = *((unsigned int*)bits + stride/4 * j + width - 2); + right_x2_data = *((unsigned int*)bits + stride/4 * j + width - 1); + } else if (bitsPerPixel == 1) { + unsigned char temp; + temp = *((unsigned char*)glyph_pixmap->devPrivate.ptr + + glyph_pixmap->devKind * j) & 0x3; + left_x1_data = temp & 0x1; + left_x2_data = temp & 0x2; + + temp = *((unsigned char*)glyph_pixmap->devPrivate.ptr + + glyph_pixmap->devKind * j + + (glyph_pixmap->drawable.width - 2)/8); + right_x1_data = temp + & (1 << ((glyph_pixmap->drawable.width - 2) % 8)); + temp = *((unsigned char*)glyph_pixmap->devPrivate.ptr + + glyph_pixmap->devKind * j + + (glyph_pixmap->drawable.width - 1)/8); + right_x2_data = temp + & (1 << ((glyph_pixmap->drawable.width - 1) % 8)); + } + left_x1_map |= (left_x1_data !=0) << j; + left_x2_map |= (left_x2_data !=0) << j; + right_x1_map |= (right_x1_data !=0) << j; + right_x2_map |= (right_x2_data !=0) << j; + } + + priv->left_x1_map = left_x1_map; + priv->left_x2_map = left_x2_map; + priv->right_x1_map = right_x1_map; + priv->right_x2_map = right_x2_map; + priv->has_edge_map = TRUE; + return; +} + + + /** * Returns TRUE if the glyphs in the lists intersect. Only checks based on * bounding box, which appears to be good enough to catch most cases at least. */ static Bool -glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) +glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, + PictFormatShort mask_format, + ScreenPtr screen, Bool check_fake_overlap) { int x1, x2, y1, y2; int n; int x, y; BoxRec extents; Bool first = TRUE; + struct glamor_glyph *priv; x = 0; y = 0; @@ -370,6 +458,11 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) extents.x2 = 0; extents.y2 = 0; while (nlist--) { + BoxRec left_box, right_box; + Bool has_left_edge_box = FALSE, has_right_edge_box = FALSE; + Bool left_to_right = TRUE; + struct glamor_glyph *left_priv, *right_priv; + x += list->xOff; y += list->yOff; n = list->len; @@ -383,17 +476,22 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) y += glyph->info.yOff; continue; } - + if (mask_format + && mask_format != GlyphPicture(glyph)[screen->myNum]->format) + return TRUE; x1 = x - glyph->info.x; if (x1 < MINSHORT) x1 = MINSHORT; y1 = y - glyph->info.y; if (y1 < MINSHORT) y1 = MINSHORT; + if (check_fake_overlap) + priv = glamor_glyph_get_private(glyph); x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + if (x2 > MAXSHORT) x2 = MAXSHORT; - y2 = y1 + glyph->info.height; if (y2 > MAXSHORT) y2 = MAXSHORT; @@ -402,23 +500,109 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) extents.y1 = y1; extents.x2 = x2; extents.y2 = y2; + + if (check_fake_overlap && priv + && priv->has_edge_map && glyph->info.yOff == 0) { + left_box.x1 = x1; + left_box.x2 = x1 + 1; + left_box.y1 = y1; + + right_box.x1 = x2 - 2; + right_box.x2 = x2 - 1; + right_box.y1 = y1; + left_priv = right_priv = priv; + has_left_edge_box = TRUE; + has_right_edge_box = TRUE; + } + first = FALSE; } else { + if (x1 < extents.x2 && x2 > extents.x1 && y1 < extents.y2 && y2 > extents.y1) { - return TRUE; - } + if (check_fake_overlap && priv + && priv->has_edge_map && glyph->info.yOff == 0) { + int left_dx, right_dx; + unsigned long long intersected; - if (x1 < extents.x1) - extents.x1 = x1; - if (x2 > extents.x2) - extents.x2 = x2; - if (y1 < extents.y1) - extents.y1 = y1; - if (y2 > extents.y2) - extents.y2 = y2; + left_dx = has_left_edge_box ? 1 : 0; + right_dx = has_right_edge_box ? 1 : 0; + + if (x1 + 1 < extents.x2 - right_dx && x2 - 1 > extents.x1 + left_dx) + return TRUE; + + if (left_to_right && has_right_edge_box) { + if (x1 == right_box.x1) { + intersected = ((priv->left_x1_map & right_priv->right_x1_map) + | (priv->left_x2_map & right_priv->right_x2_map)); + if (intersected) + return TRUE; + } else if (x1 == right_box.x2) { + intersected = (priv->left_x1_map & right_priv->right_x2_map); + if (intersected) { + #ifdef GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK + /* tolerate with two pixels overlap. */ + intersected &= ~(1<<__fls(intersected)); + if ((intersected & (intersected - 1))) + #endif + return TRUE; + } + } + } else if (!left_to_right && has_left_edge_box) { + if (x2 - 1 == left_box.x1) { + intersected = (priv->right_x2_map & left_priv->left_x1_map); + if (intersected) { + #ifdef GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK + /* tolerate with two pixels overlap. */ + intersected &= ~(1<<__fls(intersected)); + if ((intersected & (intersected - 1))) + #endif + return TRUE; + } + } else if (x2 - 1 == right_box.x2) { + if ((priv->right_x1_map & left_priv->left_x1_map) + || (priv->right_x2_map & left_priv->left_x2_map)) + return TRUE; + } + } else { + if (x1 < extents.x2 && x1 + 2 > extents.x1) + return TRUE; + } + } else + return TRUE; + } } + + if (check_fake_overlap && priv + && priv->has_edge_map && glyph->info.yOff == 0) { + if (!has_left_edge_box || x1 < extents.x1) { + left_box.x1 = x1; + left_box.x2 = x1 + 1; + left_box.y1 = y1; + has_left_edge_box = TRUE; + left_priv = priv; + } + + if (!has_right_edge_box || x2 > extents.x2) { + right_box.x1 = x2 - 2; + right_box.x2 = x2 - 1; + right_box.y1 = y1; + has_right_edge_box = TRUE; + right_priv = priv; + } + } + + if (x1 < extents.x1) + extents.x1 = x1; + if (x2 > extents.x2) + extents.x2 = x2; + + if (y1 < extents.y1) + extents.y1 = y1; + if (y2 > extents.y2) + extents.y2 = y2; + x += glyph->info.xOff; y += glyph->info.yOff; } @@ -427,7 +611,6 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs) return FALSE; } - static inline unsigned int glamor_glyph_size_to_count(int size) { @@ -457,7 +640,7 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, glamor_glyph_cache_t *cache = &glamor->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != 0]; - struct glamor_glyph *priv = NULL; + struct glamor_glyph *priv = NULL, *evicted_priv = NULL; int size, mask, pos, s; if (glyph->info.width > GLYPH_MAX_SIZE @@ -472,6 +655,8 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, s = glamor_glyph_size_to_count(size); mask = glamor_glyph_count_to_mask(s); pos = (cache->count + s - 1) & mask; + + priv = glamor_glyph_get_private(glyph); if (pos < GLYPH_CACHE_SIZE) { cache->count = pos + s; } else { @@ -482,34 +667,35 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, if (evicted == NULL) continue; - priv = glamor_glyph_get_private(evicted); - if (priv->size >= s) { + evicted_priv = glamor_glyph_get_private(evicted); + assert(evicted_priv->pos == i); + if (evicted_priv->size >= s) { cache->glyphs[i] = NULL; - glamor_glyph_set_private(evicted, NULL); + evicted_priv->cached = FALSE; pos = cache->evict & glamor_glyph_size_to_mask(size); } else - priv = NULL; + evicted_priv = NULL; break; } - if (priv == NULL) { + if (evicted_priv == NULL) { int count = glamor_glyph_size_to_count(size); mask = glamor_glyph_count_to_mask(count); pos = cache->evict & mask; for (s = 0; s < count; s++) { GlyphPtr evicted = cache->glyphs[pos + s]; if (evicted != NULL) { - if (priv != NULL) - free(priv); - priv = + evicted_priv = glamor_glyph_get_private (evicted); - glamor_glyph_set_private(evicted, - NULL); + + assert(evicted_priv->pos == pos + s); + evicted_priv->cached = FALSE; cache->glyphs[pos + s] = NULL; } } + } /* And pick a new eviction position */ cache->evict = rand() % GLYPH_CACHE_SIZE; @@ -519,9 +705,10 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, priv = malloc(sizeof(struct glamor_glyph)); if (priv == NULL) return NULL; + glamor_glyph_set_private(glyph, priv); + priv->has_edge_map = FALSE; } - glamor_glyph_set_private(glyph, priv); cache->glyphs[pos] = glyph; priv->cache = cache; @@ -543,6 +730,11 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, glamor_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, priv->y); +#ifndef GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK + if (priv->has_edge_map == FALSE && glyph->info.width >= 2) + glamor_glyph_priv_get_edge_map(glyph, priv, glyph_picture); +#endif + priv->cached = TRUE; *out_x = priv->x; *out_y = priv->y; @@ -554,6 +746,7 @@ static glamor_glyph_cache_result_t glamor_buffer_glyph(ScreenPtr screen, glamor_glyph_buffer_t * buffer, GlyphPtr glyph, int x_glyph, int y_glyph, + int dx, int dy, int w, int h, glyphs_flush glyphs_flush, void *flush_arg) { glamor_screen_private *glamor_screen = @@ -588,23 +781,25 @@ glamor_buffer_glyph(ScreenPtr screen, priv = glamor_glyph_get_private(glyph); - if (priv) { + if (priv && priv->cached) { rect = &buffer->rects[buffer->count++]; - rect->x_src = priv->x; - rect->y_src = priv->y; + rect->x_src = priv->x + dx; + rect->y_src = priv->y + dy; if (buffer->source == NULL) buffer->source = priv->cache->picture; + assert(priv->cache->glyphs[priv->pos] == glyph); } else { if (glyphs_flush) (*glyphs_flush)(flush_arg); source = glamor_glyph_cache(screen, glyph, &x, &y); if (source != NULL) { rect = &buffer->rects[buffer->count++]; - rect->x_src = x; - rect->y_src = y; + rect->x_src = x + dx; + rect->y_src = y + dy; if (buffer->source == NULL) buffer->source = source; } else { + /* Couldn't find the glyph in the cache, use the glyph picture directly */ source = GlyphPicture(glyph)[screen->myNum]; if (buffer->source && buffer->source != source @@ -613,18 +808,16 @@ glamor_buffer_glyph(ScreenPtr screen, buffer->source = source; rect = &buffer->rects[buffer->count++]; - rect->x_src = 0; - rect->y_src = 0; + rect->x_src = 0 + dx; + rect->y_src = 0 + dy; } + priv = glamor_glyph_get_private(glyph); } rect->x_dst = x_glyph - glyph->info.x; rect->y_dst = y_glyph - glyph->info.y; - rect->width = glyph->info.width; - rect->height = glyph->info.height; - - /* Couldn't find the glyph in the cache, use the glyph picture directly */ - + rect->width = w; + rect->height = h; return GLAMOR_GLYPH_SUCCESS; } @@ -708,7 +901,6 @@ glamor_glyphs_via_mask(CARD8 op, fill_rect.width = width; fill_rect.height = height; gc->ops->PolyFillRect(&mask_pixmap->drawable, gc, 1, &fill_rect); - FreeScratchGC(gc); x = -extents.x1; y = -extents.y1; @@ -734,6 +926,8 @@ glamor_glyphs_via_mask(CARD8 op, glamor_buffer_glyph(screen, &buffer, glyph, x, y, + 0, 0, + glyph->info.width, glyph->info.height, flush_func, (void*)&arg); } @@ -800,7 +994,8 @@ glamor_glyphs_to_dst(CARD8 op, PicturePtr dst, INT16 x_src, INT16 y_src, - int nlist, GlyphListPtr list, GlyphPtr * glyphs) + int nlist, GlyphListPtr list, + GlyphPtr * glyphs) { ScreenPtr screen = dst->pDrawable->pScreen; int x = 0, y = 0; @@ -809,14 +1004,21 @@ glamor_glyphs_to_dst(CARD8 op, GlyphPtr glyph; glamor_glyph_buffer_t buffer; struct glyphs_flush_dst_arg arg; + BoxPtr rects; + int nrect; buffer.count = 0; buffer.source = NULL; + + rects = REGION_RECTS(dst->pCompositeClip); + nrect = REGION_NUM_RECTS(dst->pCompositeClip); + while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { + int i; glyph = *glyphs++; if (glyph->info.width > 0 @@ -836,12 +1038,41 @@ glamor_glyphs_to_dst(CARD8 op, } else flush_func = NULL; - glamor_buffer_glyph(screen, - &buffer, - glyph, x, y, - flush_func, - (void*)&arg); + for (i = 0; i < nrect; i++) { + int dst_x, dst_y; + int dx, dy; + int x2, y2; + dst_x = x - glyph->info.x; + dst_y = y - glyph->info.y; + x2 = dst_x + glyph->info.width; + y2 = dst_y + glyph->info.height; + dx = dy = 0; + if (rects[i].y1 >= y2) + break; + + if (dst_x < rects[i].x1) + dx = rects[i].x1 - dst_x, dst_x = rects[i].x1; + if (x2 > rects[i].x2) + x2 = rects[i].x2; + if (dst_y < rects[i].y1) + dy = rects[i].y1 - dst_y, dst_y = rects[i].y1; + if (y2 > rects[i].y2) + y2 = rects[i].y2; + + if (dst_x < x2 && dst_y < y2) { + + glamor_buffer_glyph(screen, + &buffer, + glyph, + dst_x + glyph->info.x, + dst_y + glyph->info.y, + dx, dy, + x2 - dst_x, y2 - dst_y, + flush_func, + (void*)&arg); + } + } } x += glyph->info.xOff; @@ -869,39 +1100,59 @@ _glamor_glyphs(CARD8 op, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, - INT16 y_src, int nlist, GlyphListPtr list, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs, Bool fallback) { - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ - if (!mask_format) { - Bool same_format = TRUE; - int i; + Bool intersected = FALSE; + PictFormatShort format; +#ifndef GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK + Bool check_fake_overlap = TRUE; + if (!(op == PictOpOver + || op == PictOpAdd + || op == PictOpXor)) { + /* C = (0,0,0,0) D = glyphs , SRC = A, DEST = B (faked overlapped glyphs, overlapped with (0,0,0,0)). + * For those op, (A IN (C ADD D)) OP B != (A IN D) OP ((A IN C) OP B) + * or (A IN (D ADD C)) OP B != (A IN C) OP ((A IN D) OP B) + * We need to split the faked regions to three or two, and composite the disoverlapped small + * boxes one by one. For other Ops, it's safe to composite the whole box. */ + check_fake_overlap = FALSE; + } +#else + Bool check_fake_overlap = FALSE; +#endif - mask_format = list[0].format; + if (!mask_format || (((nlist == 1 && list->len == 1) || op == PictOpAdd) + && (dst->format == ((mask_format->depth << 24) | mask_format->format)))) { + glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, + list, glyphs); + return TRUE; + } - for (i = 0; i < nlist; i++) { - if (mask_format->format != list[i].format->format) { - same_format = FALSE; - break; - } - } + if (mask_format) + format = mask_format->depth << 24 | mask_format->format; + else + format = 0; - if (!same_format || (mask_format->depth != 1 && - glamor_glyphs_intersect(nlist, list, - glyphs))) { - mask_format = NULL; - } + intersected = glamor_glyphs_intersect(nlist, list, glyphs, + format, dst->pDrawable->pScreen, + check_fake_overlap); + + if (!intersected) { + glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, + list, glyphs); + return TRUE; } if (mask_format) glamor_glyphs_via_mask(op, src, dst, mask_format, x_src, y_src, nlist, list, glyphs); - else - glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, - list, glyphs); + else { + /* No mask_format and has intersect and glyphs have different format. + * XXX do we need to implement a new glyphs rendering function for + * this case?*/ + glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, list, glyphs); + } + return TRUE; } @@ -913,7 +1164,7 @@ glamor_glyphs(CARD8 op, INT16 x_src, INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - _glamor_glyphs(op, src, dst, mask_format, x_src, + _glamor_glyphs(op, src, dst, mask_format, x_src, y_src, nlist, list, glyphs, TRUE); } @@ -923,10 +1174,10 @@ glamor_glyphs_nf(CARD8 op, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, - INT16 y_src, int nlist, + INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { - return _glamor_glyphs(op, src, dst, mask_format, x_src, + return _glamor_glyphs(op, src, dst, mask_format, x_src, y_src, nlist, list, glyphs, FALSE); } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 055077cc1..989bacc1a 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -971,5 +971,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #if 0 #define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif +//#define GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK +#define GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK #endif /* GLAMOR_PRIV_H */ diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 4d8663637..ab91f313d 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -1732,6 +1732,30 @@ static inline void glamor_compare_pictures( ScreenPtr screen, return; } +#ifdef __i386__ +static inline unsigned long __fls(unsigned long x) +{ + asm("bsr %1,%0" + : "=r" (x) + : "rm" (x)); + return x; +} +#else +static inline unsigned long __fls(unsigned long x) +{ + int n; + + if (x == 0) return(0); + n = 0; + if (x <= 0x0000FFFF) {n = n +16; x = x <<16;} + if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;} + if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;} + if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;} + if (x <= 0x7FFFFFFF) {n = n + 1;} + return 31 - n; +} +#endif + static inline void glamor_make_current(ScreenPtr screen) { glamor_egl_make_current(screen); From 21916cf84f0cd9ada8701650d39b5cf67646eaf7 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 25 Jun 2012 16:37:22 +0800 Subject: [PATCH 405/462] glamor_composite_glyph: Optimize glyphs with non-solid pattern. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 88 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b33d96996..e2be4d758 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1916,12 +1916,48 @@ glamor_composite_nf(CARD8 op, FALSE); } +static void +glamor_get_src_rect_extent(int nrect, + glamor_composite_rect_t *rects, + BoxPtr extent) +{ + extent->x1 = MAXSHORT; + extent->y1 = MAXSHORT; + extent->x2 = MINSHORT; + extent->y2 = MINSHORT; + + while(nrect--) { + if (extent->x1 > rects->x_src) + extent->x1 = rects->x_src; + if (extent->y1 > rects->y_src) + extent->y1 = rects->y_src; + if (extent->x2 < rects->x_src + rects->width) + extent->x2 = rects->x_src + rects->width; + if (extent->y2 < rects->y_src + rects->height) + extent->y2 = rects->y_src + rects->height; + rects++; + } +} + +static void +glamor_composite_src_rect_translate(int nrect, + glamor_composite_rect_t *rects, + int x, int y) +{ + while(nrect--) { + rects->x_src += x; + rects->y_src += y; + rects++; + } +} + void glamor_composite_glyph_rects(CARD8 op, PicturePtr src, PicturePtr mask, PicturePtr dst, int nrect, glamor_composite_rect_t * rects) { int n; + PicturePtr temp_src = NULL; glamor_composite_rect_t *r; Bool ok; @@ -1933,41 +1969,69 @@ glamor_composite_glyph_rects(CARD8 op, glamor_pixmap_private *src_pixmap_priv = NULL; glamor_pixmap_private *mask_pixmap_priv = NULL; glamor_pixmap_private *dst_pixmap_priv; + glamor_pixmap_private *temp_src_priv = NULL; + BoxRec src_extent; + + dst_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(dst->pDrawable)); - dst_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(dst->pDrawable)); if (mask && mask->pDrawable) - mask_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(mask->pDrawable)); + mask_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(mask->pDrawable)); if (src->pDrawable) - src_pixmap_priv = glamor_get_pixmap_private(glamor_get_drawable_pixmap(src->pDrawable)); + src_pixmap_priv = glamor_get_pixmap_private + (glamor_get_drawable_pixmap(src->pDrawable)); + + if (!src->pDrawable + && (src->pSourcePict->type != SourcePictTypeSolidFill)) { + glamor_get_src_rect_extent(nrect, rects, &src_extent); + temp_src = glamor_convert_gradient_picture(dst->pDrawable->pScreen, + src, + src_extent.x1, src_extent.y1, + src_extent.x2 - src_extent.x1, + src_extent.y2 - src_extent.y1); + if (!temp_src) + goto fallback; + + temp_src_priv = glamor_get_pixmap_private + ((PixmapPtr)(temp_src->pDrawable)); + glamor_composite_src_rect_translate(nrect, rects, + -src_extent.x1, -src_extent.y1); + } else { + temp_src = src; + temp_src_priv = src_pixmap_priv; + } if (mask && mask->componentAlpha) { if (op == PictOpOver) { ok = glamor_composite_with_shader(PictOpOutReverse, - src, mask, dst, src_pixmap_priv, + temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects); - if (!ok) + if (!ok) { goto fallback; + } ok |= glamor_composite_with_shader(PictOpAdd, - src, mask, dst, src_pixmap_priv, + temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects); if (ok) - return; + goto done; assert(0); } } else { - if (glamor_composite_with_shader(op, src, mask, dst, src_pixmap_priv, + if (glamor_composite_with_shader(op, temp_src, mask, dst, temp_src_priv, mask_pixmap_priv, dst_pixmap_priv, nrect, rects)) - return; + goto done; } } + fallback: n = nrect; r = rects; while (n--) { CompositePicture(op, - src, + temp_src ? temp_src : src, mask, dst, r->x_src, r->y_src, @@ -1975,6 +2039,10 @@ fallback: r->x_dst, r->y_dst, r->width, r->height); r++; } + +done: + if (temp_src && temp_src != src) + FreePicture(temp_src, 0); } static Bool From 37d4022f01483eefe06b5f12e13ca2ed4003c8f0 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 25 Jun 2012 23:24:37 +0800 Subject: [PATCH 406/462] glamor_render: Optimize the two pass ca rendering. For the componentAlpha with PictOpOver, we use two pass rendering to implement it. Previous implementation call two times the glamor_composite_... independently which is very inefficient. Now we change the control flow, and do the two pass internally and avoid duplicate works. For the x11perf -rgb10text, this optimization can get about 30% improvement. Signed-off-by: Zhigang Gong --- glamor/glamor_priv.h | 71 +++++++++---- glamor/glamor_render.c | 208 +++++++++++++++++++++----------------- glamor/glamor_trapezoid.c | 5 +- 3 files changed, 171 insertions(+), 113 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 989bacc1a..4fad5cd3b 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -72,6 +72,7 @@ #define xorg_list_init list_init #endif +struct glamor_pixmap_private; typedef struct glamor_composite_shader { GLuint prog; @@ -84,26 +85,23 @@ typedef struct glamor_composite_shader { GLint mask_wh; GLint source_repeat_mode; GLint mask_repeat_mode; + union { + float source_solid_color[4]; + struct { + struct glamor_pixmap_private *source_priv; + PicturePtr source; + }; + }; + + union { + float mask_solid_color[4]; + struct { + struct glamor_pixmap_private *mask_priv; + PicturePtr mask; + }; + }; } 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; -} glamor_composite_rect_t; - - -enum glamor_vertex_type { - GLAMOR_VERTEX_POS, - GLAMOR_VERTEX_SOURCE, - GLAMOR_VERTEX_MASK -}; - enum shader_source { SHADER_SOURCE_SOLID, SHADER_SOURCE_TEXTURE, @@ -133,6 +131,32 @@ struct shader_key { enum shader_in in; }; +struct blendinfo { + Bool dest_alpha; + Bool source_alpha; + GLenum source_blend; + GLenum dest_blend; +}; + +typedef struct { + 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; + + +enum glamor_vertex_type { + GLAMOR_VERTEX_POS, + GLAMOR_VERTEX_SOURCE, + GLAMOR_VERTEX_MASK +}; + + enum gradient_shader { SHADER_GRADIENT_LINEAR, SHADER_GRADIENT_RADIAL, @@ -463,7 +487,6 @@ typedef enum glamor_pixmap_status { GLAMOR_UPLOAD_FAILED } glamor_pixmap_status_t; - extern DevPrivateKey glamor_screen_private_key; extern DevPrivateKey glamor_pixmap_private_key; static inline glamor_screen_private * @@ -716,6 +739,7 @@ PicturePtr glamor_convert_gradient_picture(ScreenPtr screen, PicturePtr source, int x_source, int y_source, int width, int height); + Bool glamor_composite_choose_shader(CARD8 op, PicturePtr source, PicturePtr mask, @@ -724,7 +748,16 @@ Bool glamor_composite_choose_shader(CARD8 op, glamor_pixmap_private *mask_pixmap_priv, glamor_pixmap_private *dest_pixmap_priv, struct shader_key *s_key, + glamor_composite_shader **shader, + struct blendinfo *op_info, PictFormatShort *psaved_source_format); + +void +glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, + struct shader_key *key, + glamor_composite_shader *shader, + struct blendinfo *op_info); + void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts); void glamor_emit_composite_vert(ScreenPtr screen, const float *src_coords, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index e2be4d758..5e5ae7829 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -43,14 +43,6 @@ //#define DEBUGRegionPrint(x) do {} while (0) #define DEBUGRegionPrint RegionPrint #endif - -struct blendinfo { - 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}, @@ -481,13 +473,11 @@ glamor_fini_composite_shaders(ScreenPtr screen) static Bool glamor_set_composite_op(ScreenPtr screen, - CARD8 op, PicturePtr dest, PicturePtr mask) + CARD8 op, struct blendinfo *op_info_result, + PicturePtr dest, PicturePtr mask) { GLenum source_blend, dest_blend; struct blendinfo *op_info; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_gl_dispatch *dispatch; if (op >= ARRAY_SIZE(composite_op_info)) { glamor_fallback("unsupported render op %d \n", op); @@ -518,25 +508,20 @@ glamor_set_composite_op(ScreenPtr screen, dest_blend = GL_ONE_MINUS_SRC_COLOR; } - dispatch = glamor_get_dispatch(glamor_priv); - if (source_blend == GL_ONE && dest_blend == GL_ZERO) { - dispatch->glDisable(GL_BLEND); - } else { - dispatch->glEnable(GL_BLEND); - dispatch->glBlendFunc(source_blend, dest_blend); - } - glamor_put_dispatch(glamor_priv); + op_info_result->source_blend = source_blend; + op_info_result->dest_blend = dest_blend; + op_info_result->source_alpha = op_info->source_alpha; + op_info_result->dest_alpha = op_info->dest_alpha; + return TRUE; } static void -glamor_set_composite_texture(ScreenPtr screen, int unit, +glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, PicturePtr picture, glamor_pixmap_private * pixmap_priv, GLuint wh_location, GLuint repeat_location) { - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; float wh[4]; int repeat_type; @@ -956,10 +941,11 @@ Bool glamor_composite_choose_shader(CARD8 op, glamor_pixmap_private *mask_pixmap_priv, glamor_pixmap_private *dest_pixmap_priv, struct shader_key *s_key, + glamor_composite_shader **shader, + struct blendinfo *op_info, PictFormatShort *psaved_source_format) { ScreenPtr screen = dest->pDrawable->pScreen; - glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap; PixmapPtr source_pixmap = NULL; PixmapPtr mask_pixmap = NULL; @@ -969,8 +955,6 @@ Bool glamor_composite_choose_shader(CARD8 op, struct shader_key key; GLfloat source_solid_color[4]; GLfloat mask_solid_color[4]; - glamor_composite_shader *shader = NULL; - glamor_gl_dispatch *dispatch = NULL; Bool ret = FALSE; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { @@ -1175,44 +1159,33 @@ Bool glamor_composite_choose_shader(CARD8 op, goto fail; } - glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - if (!glamor_set_composite_op(screen, op, dest, mask)) { + if (!glamor_set_composite_op(screen, op, op_info, dest, mask)) goto fail; - } - shader = glamor_lookup_composite_shader(screen, &key); - if (shader->prog == 0) { + *shader = glamor_lookup_composite_shader(screen, &key); + if ((*shader)->prog == 0) { glamor_fallback("no shader program for this" "render acccel mode\n"); goto fail; } - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glUseProgram(shader->prog); - - if (key.source == SHADER_SOURCE_SOLID) { - glamor_set_composite_solid(dispatch, source_solid_color, - shader->source_uniform_location); - } else { - glamor_set_composite_texture(screen, 0, source, - source_pixmap_priv, shader->source_wh, - shader->source_repeat_mode); + if (key.source == SHADER_SOURCE_SOLID) + memcpy(&(*shader)->source_solid_color[0], + source_solid_color, 4*sizeof(float)); + else { + (*shader)->source_priv = source_pixmap_priv; + (*shader)->source = source; } - if (key.mask != SHADER_MASK_NONE) { - if (key.mask == SHADER_MASK_SOLID) { - glamor_set_composite_solid(dispatch, - mask_solid_color, - shader->mask_uniform_location); - } else { - glamor_set_composite_texture(screen, 1, mask, - mask_pixmap_priv, shader->mask_wh, - shader->mask_repeat_mode); - } + if (key.mask == SHADER_MASK_SOLID) + memcpy(&(*shader)->mask_solid_color[0], + mask_solid_color, 4*sizeof(float)); + else { + (*shader)->mask_priv = mask_pixmap_priv; + (*shader)->mask = mask; } - glamor_put_dispatch(glamor_priv); ret = TRUE; memcpy(s_key, &key, sizeof(key)); *psaved_source_format = saved_source_format; @@ -1225,6 +1198,56 @@ done: return ret; } +void +glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv, + struct shader_key *key, + glamor_composite_shader *shader, + struct blendinfo *op_info) +{ + glamor_gl_dispatch *dispatch; + glamor_screen_private *glamor_priv; + + glamor_priv = dest_priv->base.glamor_priv; + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glUseProgram(shader->prog); + + if (key->source == SHADER_SOURCE_SOLID) { + glamor_set_composite_solid(dispatch, + shader->source_solid_color, + shader->source_uniform_location); + } else { + glamor_set_composite_texture(glamor_priv, 0, + shader->source, + shader->source_priv, shader->source_wh, + shader->source_repeat_mode); + } + + if (key->mask != SHADER_MASK_NONE) { + if (key->mask == SHADER_MASK_SOLID) { + glamor_set_composite_solid(dispatch, + shader->mask_solid_color, + shader->mask_uniform_location); + } else { + glamor_set_composite_texture(glamor_priv, 1, + shader->mask, + shader->mask_priv, shader->mask_wh, + shader->mask_repeat_mode); + } + } + + if (op_info->source_blend == GL_ONE + && op_info->dest_blend == GL_ZERO) { + dispatch->glDisable(GL_BLEND); + } else { + dispatch->glEnable(GL_BLEND); + dispatch->glBlendFunc(op_info->source_blend, + op_info->dest_blend); + } + + glamor_put_dispatch(glamor_priv); +} + static Bool glamor_composite_with_shader(CARD8 op, PicturePtr source, @@ -1233,7 +1256,8 @@ glamor_composite_with_shader(CARD8 op, glamor_pixmap_private *source_pixmap_priv, glamor_pixmap_private *mask_pixmap_priv, glamor_pixmap_private *dest_pixmap_priv, - int nrect, glamor_composite_rect_t * rects) + int nrect, glamor_composite_rect_t * rects, + Bool two_pass_ca) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_screen_private *glamor_priv = dest_pixmap_priv->base.glamor_priv; @@ -1244,7 +1268,7 @@ glamor_composite_with_shader(CARD8 op, GLfloat dst_xscale, dst_yscale; GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1; - struct shader_key key; + struct shader_key key, key_ca; float *vertices; int dest_x_off, dest_y_off; int source_x_off, source_y_off; @@ -1255,14 +1279,30 @@ glamor_composite_with_shader(CARD8 op, int vert_stride = 4; int nrect_max; Bool ret = FALSE; + glamor_composite_shader *shader = NULL, *shader_ca = NULL; + struct blendinfo op_info, op_info_ca; if(!glamor_composite_choose_shader(op, source, mask, dest, source_pixmap_priv, mask_pixmap_priv, dest_pixmap_priv, - &key, &saved_source_format)) { + &key, &shader, &op_info, + &saved_source_format)) { glamor_fallback("glamor_composite_choose_shader failed\n"); return ret; } + if (two_pass_ca) { + if(!glamor_composite_choose_shader(PictOpAdd, source, mask, dest, + source_pixmap_priv, mask_pixmap_priv, + dest_pixmap_priv, + &key_ca, &shader_ca, &op_info_ca, + &saved_source_format)) { + glamor_fallback("glamor_composite_choose_shader failed\n"); + return ret; + } + } + + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info); dispatch = glamor_get_dispatch(glamor_priv); @@ -1277,8 +1317,7 @@ glamor_composite_with_shader(CARD8 op, pixmap_priv_get_dest_scale(dest_pixmap_priv, &dst_xscale, &dst_yscale); if (glamor_priv->has_source_coords) { - source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); - source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + source_pixmap = source_pixmap_priv->base.pixmap; glamor_get_drawable_deltas(source->pDrawable, source_pixmap, &source_x_off, &source_y_off); @@ -1292,8 +1331,7 @@ glamor_composite_with_shader(CARD8 op, } if (glamor_priv->has_mask_coords) { - mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); - mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + mask_pixmap = mask_pixmap_priv->base.pixmap; glamor_get_drawable_deltas(mask->pDrawable, mask_pixmap, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, @@ -1369,6 +1407,16 @@ glamor_composite_with_shader(CARD8 op, } glamor_flush_composite_rects(screen); nrect -= rect_processed; + if (two_pass_ca) { + glamor_composite_set_shader_blend(dest_pixmap_priv, + &key_ca, shader_ca, + &op_info_ca); + glamor_flush_composite_rects(screen); + if (nrect) + glamor_composite_set_shader_blend(dest_pixmap_priv, + &key, shader, + &op_info); + } } dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -1475,7 +1523,6 @@ glamor_composite_clipped_region(CARD8 op, glamor_pixmap_private *temp_src_priv = source_pixmap_priv; glamor_pixmap_private *temp_mask_priv = mask_pixmap_priv; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; - BoxPtr extent; glamor_composite_rect_t rect[10]; glamor_composite_rect_t *prect = rect; @@ -1486,6 +1533,8 @@ glamor_composite_clipped_region(CARD8 op, int height; BoxPtr box; int nbox; + Bool two_pass_ca = FALSE; + extent = RegionExtents(region); box = RegionRects(region); nbox = RegionNumRects(region); @@ -1557,23 +1606,8 @@ glamor_composite_clipped_region(CARD8 op, if (mask && mask->componentAlpha) { if (op == PictOpOver) { - glamor_composite_clipped_region(PictOpOutReverse, - temp_src, temp_mask, dest, - temp_src_priv, temp_mask_priv, dest_pixmap_priv, - region, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest); - - glamor_composite_clipped_region(PictOpAdd, - temp_src, temp_mask, dest, - temp_src_priv, temp_mask_priv, dest_pixmap_priv, - region, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest); - ok = TRUE; - goto out; + two_pass_ca = TRUE; + op = PictOpOutReverse; } } @@ -1624,7 +1658,7 @@ glamor_composite_clipped_region(CARD8 op, ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, temp_src_priv, temp_mask_priv, dest_pixmap_priv, - box_cnt, prect); + box_cnt, prect, two_pass_ca); if (!ok) break; nbox -= box_cnt; @@ -1959,7 +1993,6 @@ glamor_composite_glyph_rects(CARD8 op, int n; PicturePtr temp_src = NULL; glamor_composite_rect_t *r; - Bool ok; ValidatePicture(src); ValidatePicture(dst); @@ -2004,27 +2037,18 @@ glamor_composite_glyph_rects(CARD8 op, if (mask && mask->componentAlpha) { if (op == PictOpOver) { - ok = glamor_composite_with_shader(PictOpOutReverse, + if (glamor_composite_with_shader(PictOpOutReverse, temp_src, mask, dst, temp_src_priv, - mask_pixmap_priv, dst_pixmap_priv, nrect, rects); - if (!ok) { - goto fallback; - } - ok |= glamor_composite_with_shader(PictOpAdd, - temp_src, mask, dst, temp_src_priv, - mask_pixmap_priv, dst_pixmap_priv, nrect, rects); - if (ok) + mask_pixmap_priv, dst_pixmap_priv, nrect, rects, + TRUE)) goto done; - assert(0); } } else { if (glamor_composite_with_shader(op, temp_src, mask, dst, temp_src_priv, - mask_pixmap_priv, dst_pixmap_priv, nrect, rects)) + mask_pixmap_priv, dst_pixmap_priv, nrect, rects, FALSE)) goto done; } } - - fallback: n = nrect; r = rects; diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 3ad9e5007..5dd2792d7 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -701,12 +701,13 @@ _glamor_trapezoids_with_shader(CARD8 op, ret = glamor_composite_choose_shader(op, temp_src, NULL, dst, temp_src_priv, NULL, dest_pixmap_priv, - &key, &saved_source_format); + &key, &shader, &op_info, &saved_source_format); if (ret == FALSE) { DEBUGF("can not set the shader program for composite\n"); goto TRAPEZOID_RESET_GL; } - + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); + glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, op_info); 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); From 682f5d2989306856c0c193b0b4abd8c104a9ba92 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 26 Jun 2012 13:09:05 +0800 Subject: [PATCH 407/462] glamor_largepixmap: Walkaround for large texture's upload. I met a problem with large texture (larger than 7000x7000)'s uploading on SNB platform. The map_gtt get back a mapped VA without error, but write to that virtual address triggers BUS error. This work around is to avoid that direct uploading. Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 6 +++++- glamor/glamor_priv.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index ce243abcf..10066a6b5 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -497,7 +497,11 @@ ready_to_upload: if (no_alpha == 0 && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING - && !need_flip) { + && !need_flip +#ifdef WALKAROUND_LARGE_TEXTURE_MAP + && pixmap_priv->type != GLAMOR_TEXTURE_LARGE +#endif + ) { int fbo_x_off, fbo_y_off; assert(pixmap_priv->base.fbo->tex); pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 4fad5cd3b..642aff68c 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -1001,6 +1001,7 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, //#define GLAMOR_TRAPEZOID_SHADER #endif #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 +#define WALKAROUND_LARGE_TEXTURE_MAP #if 0 #define MAX_FBO_SIZE 32 /* For test purpose only. */ #endif From 3873d412f018b975feaa000cb7ef337feaeee37d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 26 Jun 2012 15:39:24 +0800 Subject: [PATCH 408/462] glamor_render: Don't allocate buffer for vbo each time. We can reuse the last one if the last one is big enough to contain current vertext data. In the meantime, Use MapBufferRange instead of MapBuffer. Testing shows, this patch brings some benefit for aa10text/rgb10text. Not too much, but indeed faster. Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 5e5ae7829..b82c7c327 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -724,10 +724,17 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; + int vert_size; + Bool need_new_buffer = FALSE; glamor_priv->vbo_offset = 0; glamor_priv->render_nr_verts = 0; - glamor_priv->vbo_size = n_verts * sizeof(float) * 2; + vert_size = n_verts * sizeof(float) * 2; + + if (glamor_priv->vbo_size < vert_size) { + glamor_priv->vbo_size = vert_size; + need_new_buffer = TRUE; + } glamor_priv->vb_stride = 2 * sizeof(float); if (glamor_priv->has_source_coords) @@ -738,10 +745,14 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - dispatch->glBufferData(GL_ARRAY_BUFFER, - n_verts * sizeof(float) * 2, - NULL, GL_DYNAMIC_DRAW); - glamor_priv->vb = dispatch->glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); + if (need_new_buffer) + dispatch->glBufferData(GL_ARRAY_BUFFER, + vert_size, + NULL, GL_DYNAMIC_DRAW); + glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER, 0, + vert_size, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + assert(glamor_priv->vb != NULL); } dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); From b8dd2a597de455ae985302d1b93d865ef9f37c7b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 26 Jun 2012 16:24:32 +0800 Subject: [PATCH 409/462] glamor_glyphs: Slightly performance tuning. As glamor_glyphs never fallback, we don't need to keep the underlying glyphs routines, just override the ps->glys Signed-off-by: Zhigang Gong --- glamor/glamor.c | 11 +++--- glamor/glamor_glyphs.c | 82 ++++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 56 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index d087b8275..0f93e98b3 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -386,8 +386,6 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_procs.trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; - glamor_priv->saved_procs.glyphs = ps->Glyphs; - ps->Glyphs = glamor_glyphs; glamor_priv->saved_procs.triangles = ps->Triangles; ps->Triangles = glamor_triangles; @@ -395,9 +393,14 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_procs.addtraps = ps->AddTraps; ps->AddTraps = glamor_add_traps; - glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph; - ps->UnrealizeGlyph = glamor_glyph_unrealize; } + + glamor_priv->saved_procs.glyphs = ps->Glyphs; + ps->Glyphs = glamor_glyphs; + + glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph; + ps->UnrealizeGlyph = glamor_glyph_unrealize; + glamor_priv->saved_procs.create_picture = ps->CreatePicture; ps->CreatePicture = glamor_create_picture; diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index fa8b55f15..c2a750d07 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -97,16 +97,9 @@ static DevPrivateKeyRec glamor_glyph_key; static inline struct glamor_glyph * glamor_glyph_get_private(GlyphPtr glyph) { - return dixGetPrivate(&glyph->devPrivates, &glamor_glyph_key); + return (struct glamor_glyph*)glyph->devPrivates; } -static inline void -glamor_glyph_set_private(GlyphPtr glyph, struct glamor_glyph *priv) -{ - dixSetPrivate(&glyph->devPrivates, &glamor_glyph_key, priv); -} - - static void glamor_unrealize_glyph_caches(ScreenPtr pScreen) { @@ -210,7 +203,8 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) Bool glamor_glyphs_init(ScreenPtr pScreen) { - if (!dixRegisterPrivateKey(&glamor_glyph_key, PRIVATE_GLYPH, 0)) + if (!dixRegisterPrivateKey(&glamor_glyph_key, + PRIVATE_GLYPH, sizeof(struct glamor_glyph))) return FALSE; /* Skip pixmap creation if we don't intend to use it. */ @@ -299,15 +293,10 @@ glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph) struct glamor_glyph *priv; /* Use Lookup in case we have not attached to this glyph. */ - priv = dixLookupPrivate(&glyph->devPrivates, &glamor_glyph_key); - if (priv == NULL) - return; + priv = glamor_glyph_get_private(glyph); if (priv->cached) priv->cache->glyphs[priv->pos] = NULL; - - glamor_glyph_set_private(glyph, NULL); - free(priv); } /* Cut and paste from render/glyph.c - probably should export it instead */ @@ -632,10 +621,10 @@ glamor_glyph_size_to_mask(int size) } static PicturePtr -glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, +glamor_glyph_cache(glamor_screen_private *glamor, GlyphPtr glyph, int *out_x, int *out_y) { - glamor_screen_private *glamor = glamor_get_screen_private(screen); + ScreenPtr screen = glamor->screen; PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; glamor_glyph_cache_t *cache = &glamor->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != @@ -701,14 +690,6 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, cache->evict = rand() % GLYPH_CACHE_SIZE; } - if (priv == NULL) { - priv = malloc(sizeof(struct glamor_glyph)); - if (priv == NULL) - return NULL; - glamor_glyph_set_private(glyph, priv); - priv->has_edge_map = FALSE; - } - cache->glyphs[pos] = glyph; priv->cache = cache; @@ -743,14 +724,13 @@ glamor_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, typedef void (*glyphs_flush)(void * arg); static glamor_glyph_cache_result_t -glamor_buffer_glyph(ScreenPtr screen, +glamor_buffer_glyph(glamor_screen_private *glamor_priv, glamor_glyph_buffer_t * buffer, GlyphPtr glyph, int x_glyph, int y_glyph, int dx, int dy, int w, int h, glyphs_flush glyphs_flush, void *flush_arg) { - glamor_screen_private *glamor_screen = - glamor_get_screen_private(screen); + ScreenPtr screen = glamor_priv->screen; unsigned int format = (GlyphPicture(glyph)[screen->myNum])->format; glamor_composite_rect_t *rect; PicturePtr source; @@ -763,7 +743,7 @@ glamor_buffer_glyph(ScreenPtr screen, format = PICT_a8; cache = - &glamor_screen->glyphCaches[PICT_FORMAT_RGB + &glamor_priv->glyphCaches[PICT_FORMAT_RGB (glyph_picture->format) != 0]; if (buffer->source @@ -791,7 +771,7 @@ glamor_buffer_glyph(ScreenPtr screen, } else { if (glyphs_flush) (*glyphs_flush)(flush_arg); - source = glamor_glyph_cache(screen, glyph, &x, &y); + source = glamor_glyph_cache(glamor_priv, glyph, &x, &y); if (source != NULL) { rect = &buffer->rects[buffer->count++]; rect->x_src = x + dx; @@ -863,11 +843,13 @@ glamor_glyphs_via_mask(CARD8 op, xRectangle fill_rect; struct glyphs_flush_mask_arg arg; GCPtr gc; + glamor_screen_private *glamor_priv; glamor_glyph_extents(nlist, list, glyphs, &extents); if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) return; + glamor_priv = glamor_get_screen_private(screen); width = extents.x2 - extents.x1; height = extents.y2 - extents.y1; @@ -924,7 +906,7 @@ glamor_glyphs_via_mask(CARD8 op, else flush_func = NULL; - glamor_buffer_glyph(screen, &buffer, + glamor_buffer_glyph(glamor_priv, &buffer, glyph, x, y, 0, 0, glyph->info.width, glyph->info.height, @@ -1006,6 +988,7 @@ glamor_glyphs_to_dst(CARD8 op, struct glyphs_flush_dst_arg arg; BoxPtr rects; int nrect; + glamor_screen_private *glamor_priv; buffer.count = 0; buffer.source = NULL; @@ -1013,6 +996,18 @@ glamor_glyphs_to_dst(CARD8 op, rects = REGION_RECTS(dst->pCompositeClip); nrect = REGION_NUM_RECTS(dst->pCompositeClip); + glamor_priv = glamor_get_screen_private(screen); + + arg.op = op; + arg.src = src; + arg.dst = dst; + arg.buffer = &buffer; + arg.x_src = x_src; + arg.y_src = y_src; + arg.x_dst = x_dst; + arg.y_dst = y_dst; + + while (nlist--) { x += list->xOff; y += list->yOff; @@ -1025,17 +1020,9 @@ glamor_glyphs_to_dst(CARD8 op, && glyph->info.height > 0) { glyphs_flush flush_func; - if (buffer.count) { - arg.op = op; - arg.src = src; - arg.dst = dst; - arg.buffer = &buffer; - arg.x_src = x_src; - arg.y_src = y_src; - arg.x_dst = x_dst; - arg.y_dst = y_dst; + if (buffer.count) flush_func = (glyphs_flush)glamor_glyphs_flush_dst; - } else + else flush_func = NULL; for (i = 0; i < nrect; i++) { @@ -1062,7 +1049,7 @@ glamor_glyphs_to_dst(CARD8 op, if (dst_x < x2 && dst_y < y2) { - glamor_buffer_glyph(screen, + glamor_buffer_glyph(glamor_priv, &buffer, glyph, dst_x + glyph->info.x, @@ -1081,17 +1068,8 @@ glamor_glyphs_to_dst(CARD8 op, list++; } - if (buffer.count) { - arg.op = op; - arg.src = src; - arg.dst = dst; - arg.buffer = &buffer; - arg.x_src = x_src; - arg.y_src = y_src; - arg.x_dst = x_dst; - arg.y_dst = y_dst; + if (buffer.count) glamor_glyphs_flush_dst(&arg); - } } static Bool From 90dd6ddbab864aa6c3add55c46a85d7db2c125f6 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 26 Jun 2012 17:19:16 +0800 Subject: [PATCH 410/462] glamor_copyarea: Fixed a bug introduced by 996194... Default return value should be FALSE. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 243c1f28a..ee6f8120f 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -398,7 +398,7 @@ _glamor_copy_n_to_n(DrawablePtr src, RegionRec region; ScreenPtr screen; int src_x_off, src_y_off, dst_x_off, dst_y_off; - Bool ok = TRUE; + Bool ok = FALSE; int force_clip = 0; if (nbox == 0) @@ -426,7 +426,6 @@ _glamor_copy_n_to_n(DrawablePtr src, dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, gc->alu)) { glamor_put_dispatch(glamor_priv); - ok = FALSE; goto fail; } glamor_put_dispatch(glamor_priv); @@ -549,6 +548,9 @@ _glamor_copy_n_to_n(DrawablePtr src, goto fail; } } + + if (n_src_region == 0) + ok = TRUE; free(clipped_src_regions); } else { RegionTranslate(clipped_dst_regions[i].region, @@ -571,6 +573,8 @@ _glamor_copy_n_to_n(DrawablePtr src, } RegionDestroy(clipped_dst_regions[i].region); } + if (n_dst_region == 0) + ok = TRUE; free(clipped_dst_regions); RegionUninit(®ion); } else { From d5f03ba0109bc50e159c82d3d67cffa8fc174134 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 26 Jun 2012 19:56:27 +0800 Subject: [PATCH 411/462] create_pixmap: use texture for large glyphs. As we only cache glyphs smaller than 64x64, we need to use texutre for the large glyphs. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 0f93e98b3..a0046f953 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -142,7 +142,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; if ((usage == GLAMOR_CREATE_PIXMAP_CPU - || usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE + || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 64 && h <= 64) || (w == 0 && h == 0) || !glamor_check_pixmap_fbo_depth(depth)) || (!GLAMOR_TEXTURED_LARGE_PIXMAP && From dd7924339803b51332e3fe94d36eb48549e9d24d Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 26 Jun 2012 20:00:21 +0800 Subject: [PATCH 412/462] optimize: Use likely and unlikely. Signed-off-by: Zhigang Gong --- glamor/compiler.h | 59 +++++++++++++++++++++++++++++++++++++++++++ glamor/glamor_priv.h | 2 ++ glamor/glamor_utils.h | 36 +++++++++++++------------- 3 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 glamor/compiler.h diff --git a/glamor/compiler.h b/glamor/compiler.h new file mode 100644 index 000000000..fa2895976 --- /dev/null +++ b/glamor/compiler.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Chris Wilson + * + * Copied from sna + * + */ + +#ifndef _GLAMOR_COMPILER_H_ +#define _GLAMOR_COMPILER_H_ + +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#define likely(expr) (__builtin_expect (!!(expr), 1)) +#define unlikely(expr) (__builtin_expect (!!(expr), 0)) +#define noinline __attribute__((noinline)) +#define fastcall __attribute__((regparm(3))) +#define must_check __attribute__((warn_unused_result)) +#define constant __attribute__((const)) +#else +#define likely(expr) (expr) +#define unlikely(expr) (expr) +#define noinline +#define fastcall +#define must_check +#define constant +#endif + +#ifdef HAVE_VALGRIND +#define VG(x) x +#else +#define VG(x) +#endif + +#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s))) + +#define COMPILE_TIME_ASSERT(E) ((void)sizeof(char[1 - 2*!(E)])) + +#endif /* _SNA_COMPILER_H_ */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 642aff68c..61551df0b 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -31,6 +31,8 @@ #include "config.h" #endif +#include "compiler.h" + #include #ifndef DEBUG #define NDEBUG diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index ab91f313d..88c66168a 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -59,7 +59,7 @@ #define PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, w, h) \ do { \ - if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + if (unlikely(priv->type == GLAMOR_TEXTURE_LARGE)) { \ w = priv->large.box.x2 - priv->large.box.x1; \ h = priv->large.box.y2 - priv->large.box.y1; \ } else { \ @@ -80,8 +80,8 @@ #define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \ do { \ - if (_priv_ && (_priv_)->type \ - == GLAMOR_TEXTURE_LARGE) { \ + if (unlikely(_priv_ && (_priv_)->type \ + == GLAMOR_TEXTURE_LARGE)) { \ *(_xoff_) = - (_priv_)->large.box.x1; \ *(_yoff_) = - (_priv_)->large.box.y1; \ } else { \ @@ -316,7 +316,7 @@ texcoord, yInverted) \ do { \ (texcoord)[0] = t_from_x_coord_x(xscale, _tx_); \ - if (yInverted) \ + if (likely(yInverted)) \ (texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);\ else \ (texcoord)[1] = t_from_x_coord_y(yscale, _ty_); \ @@ -339,7 +339,7 @@ tx += fbo_x_off; \ ty += fbo_y_off; \ (texcoord)[0] = t_from_x_coord_x(xscale, tx); \ - if (yInverted) \ + if (likely(yInverted)) \ (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty); \ else \ (texcoord)[1] = t_from_x_coord_y(yscale, ty); \ @@ -436,14 +436,12 @@ texcoords, \ stride) \ do { \ - if (priv->type != GLAMOR_TEXTURE_LARGE) { \ + if (likely(priv->type != GLAMOR_TEXTURE_LARGE)) { \ glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale, \ yscale, _x1_, _y1_, \ _x2_, _y2_, yInverted, \ texcoords, stride); \ } else { \ - /* For a large pixmap, if both transform and repeat are set, - * the transform must only has x and y scale factor.*/ \ float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4; \ float ttx1, tty1, ttx2, tty2, ttx3, tty3, ttx4, tty4; \ DEBUGF("original coords %d %d %d %d\n", _x1_, _y1_, _x2_, _y2_); \ @@ -512,7 +510,7 @@ (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2); \ (vertices)[2 * stride] = _t2_; \ (vertices)[3 * stride] = _t0_; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1); \ (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2);\ } \ @@ -528,7 +526,7 @@ x1, y1, x2, y2, \ yInverted, vertices, stride) \ do { \ - if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + if (unlikely(priv->type == GLAMOR_TEXTURE_LARGE)) { \ float tx1, tx2, ty1, ty2; \ int fbo_x_off, fbo_y_off; \ pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off); \ @@ -559,7 +557,7 @@ _x1_, _y1_, _x2_, _y2_, \ yInverted, vertices, stride)\ do { \ - if (priv->type == GLAMOR_TEXTURE_LARGE) { \ + if (unlikely(priv->type == GLAMOR_TEXTURE_LARGE)) { \ float tx1, tx2, ty1, ty2; \ if (repeat_type == RepeatPad) { \ tx1 = _x1_ - priv->large.box.x1; \ @@ -600,7 +598,7 @@ (vertices)[2] = t_from_x_coord_x(xscale, x2); \ (vertices)[6] = (vertices)[2]; \ (vertices)[4] = (vertices)[0]; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1); \ (vertices)[7] = t_from_x_coord_y_inverted(yscale, y2); \ } \ @@ -619,7 +617,7 @@ (vertices)[2] = (x2); \ (vertices)[4] = (vertices)[2]; \ (vertices)[6] = (vertices)[0]; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = (y1); \ (vertices)[5] = (y2); \ } \ @@ -635,7 +633,7 @@ yInverted, vertices) \ do { \ (vertices)[0] = v_from_x_coord_x(xscale, x); \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = v_from_x_coord_y_inverted(yscale, y); \ } else { \ (vertices)[1] = v_from_x_coord_y(yscale, y); \ @@ -663,7 +661,7 @@ (vertices)[2] = (x2); \ (vertices)[6] = (vertices)[2]; \ (vertices)[4] = (vertices)[0]; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = (y1); \ (vertices)[7] = (y2); \ } \ @@ -689,7 +687,7 @@ x2 + fbo_x_off); \ (vertices)[2 * stride] = _t2_; \ (vertices)[3 * stride] = _t0_; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale, \ y1 + fbo_y_off); \ (vertices)[2 * stride + 1] = _t5_ = \ @@ -723,7 +721,7 @@ (vertices)[2] = v_from_x_coord_x(xscale, x2); \ (vertices)[6] = (vertices)[2]; \ (vertices)[4] = (vertices)[0]; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1); \ (vertices)[7] = v_from_x_coord_y_inverted(yscale, y2); \ } \ @@ -739,7 +737,7 @@ yInverted, pt) \ do { \ (pt)[0] = t_from_x_coord_x(xscale, x); \ - if (yInverted) { \ + if (likely(yInverted)) { \ (pt)[1] = t_from_x_coord_y_inverted(yscale, y); \ } else { \ (pt)[1] = t_from_x_coord_y(yscale, y); \ @@ -750,7 +748,7 @@ yInverted, c) \ do { \ (c)[0] = (float)x; \ - if (yInverted) { \ + if (likely(yInverted)) { \ (c)[1] = (float)y; \ } else { \ (c)[1] = (float)height - (float)y; \ From 4d1a2173f2e5a200d1535a4a459fffd75cd5f779 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 27 Jun 2012 12:53:40 +0800 Subject: [PATCH 413/462] glamor_compositerects: Implement optimized version. Don't call miCompositeRects. Use glamor_composite_clipped_region to render those boxes at once. Also add a new function glamor_solid_boxes to fill boxes at once. Signed-off-by: Zhigang Gong --- glamor/Makefile.am | 1 + glamor/glamor.c | 8 +- glamor/glamor_compositerects.c | 278 +++++++++++++++++++++++++++++++++ glamor/glamor_fill.c | 181 +++++++++++++++------ glamor/glamor_priv.h | 14 +- glamor/glamor_utils.h | 6 + 6 files changed, 439 insertions(+), 49 deletions(-) create mode 100644 glamor/glamor_compositerects.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index e29f918c4..766aac776 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -48,6 +48,7 @@ libglamor_la_SOURCES = \ glamor_window.c\ glamor_gl_dispatch.c\ glamor_fbo.c\ + glamor_compositerects.c\ glamor.h sdk_HEADERS = glamor.h diff --git a/glamor/glamor.c b/glamor/glamor.c index a0046f953..01f6a9a8f 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -383,6 +383,7 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_procs.composite = ps->Composite; ps->Composite = glamor_composite; + glamor_priv->saved_procs.trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; @@ -395,6 +396,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) } + glamor_priv->saved_procs.composite_rects = ps->CompositeRects; + ps->CompositeRects = glamor_composite_rectangles; + glamor_priv->saved_procs.glyphs = ps->Glyphs; ps->Glyphs = glamor_glyphs; @@ -510,10 +514,12 @@ glamor_close_screen(int idx, ScreenPtr screen) ps->Composite = glamor_priv->saved_procs.composite; ps->Trapezoids = glamor_priv->saved_procs.trapezoids; - ps->Glyphs = glamor_priv->saved_procs.glyphs; ps->Triangles = glamor_priv->saved_procs.triangles; ps->CreatePicture = glamor_priv->saved_procs.create_picture; } + ps->CompositeRects = glamor_priv->saved_procs.composite_rects; + ps->Glyphs = glamor_priv->saved_procs.glyphs; + ps->UnrealizeGlyph = glamor_priv->saved_procs.unrealize_glyph; #endif screen_pixmap = screen->GetScreenPixmap(screen); glamor_set_pixmap_private(screen_pixmap, NULL); diff --git a/glamor/glamor_compositerects.c b/glamor/glamor_compositerects.c new file mode 100644 index 000000000..5fe1bbf77 --- /dev/null +++ b/glamor/glamor_compositerects.c @@ -0,0 +1,278 @@ +/* + * Copyright © 2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Zhigang Gong + * + * original author is Chris Wilson at sna. + * + */ + +#include "glamor_priv.h" +#include "mipict.h" +#include "damage.h" + +/** @file glamor_compositerects. + * + * compositeRects acceleration implementation + */ + +static int16_t bound(int16_t a, uint16_t b) +{ + int v = (int)a + (int)b; + if (v > MAXSHORT) + return MAXSHORT; + return v; +} + +static Bool +_pixman_region_init_clipped_rectangles(pixman_region16_t *region, + unsigned int num_rects, + xRectangle *rects, + int tx, int ty, + BoxPtr extents) +{ + pixman_box16_t stack_boxes[64], *boxes = stack_boxes; + pixman_bool_t ret; + unsigned int i, j; + + if (num_rects > ARRAY_SIZE(stack_boxes)) { + boxes = malloc(sizeof(pixman_box16_t) * num_rects); + if (boxes == NULL) + return FALSE; + } + + for (i = j = 0; i < num_rects; i++) { + boxes[j].x1 = rects[i].x + tx; + if (boxes[j].x1 < extents->x1) + boxes[j].x1 = extents->x1; + + boxes[j].y1 = rects[i].y + ty; + if (boxes[j].y1 < extents->y1) + boxes[j].y1 = extents->y1; + + boxes[j].x2 = bound(rects[i].x + tx, rects[i].width); + if (boxes[j].x2 > extents->x2) + boxes[j].x2 = extents->x2; + + boxes[j].y2 = bound(rects[i].y + ty, rects[i].height); + if (boxes[j].y2 > extents->y2) + boxes[j].y2 = extents->y2; + + if (boxes[j].x2 > boxes[j].x1 && boxes[j].y2 > boxes[j].y1) + j++; + } + + ret = FALSE; + if (j) + ret = pixman_region_init_rects(region, boxes, j); + + if (boxes != stack_boxes) + free(boxes); + + DEBUGF("%s: nrects=%d, region=(%d, %d), (%d, %d) x %d\n", + __FUNCTION__, num_rects, + region->extents.x1, region->extents.y1, + region->extents.x2, region->extents.y2, + j); + return ret; +} + + +void +glamor_composite_rectangles(CARD8 op, + PicturePtr dst, + xRenderColor *color, + int num_rects, + xRectangle *rects) +{ + PixmapPtr pixmap; + struct glamor_pixmap_private *priv; + pixman_region16_t region; + pixman_box16_t *boxes; + int dst_x, dst_y; + int num_boxes; + PicturePtr source = NULL; + Bool need_free_region = FALSE; + + DEBUGF("%s(op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n", + __FUNCTION__, op, + (color->alpha >> 8 << 24) | + (color->red >> 8 << 16) | + (color->green >> 8 << 8) | + (color->blue >> 8 << 0), + num_rects, + rects[0].x, rects[0].y, rects[0].width, rects[0].height); + + if (!num_rects) + return; + + if (region_is_empty(dst->pCompositeClip)) { + DEBUGF("%s: empty clip, skipping\n", __FUNCTION__); + return; + } + + pixmap = glamor_get_drawable_pixmap(dst->pDrawable); + priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) + goto fallback; + if (dst->alphaMap) { + DEBUGF("%s: fallback, dst has an alpha-map\n", __FUNCTION__); + goto fallback; + } + + if ((color->red|color->green|color->blue|color->alpha) <= 0x00ff) { + switch (op) { + case PictOpOver: + case PictOpOutReverse: + case PictOpAdd: + return; + case PictOpInReverse: + case PictOpSrc: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOut; + break; + case PictOpXor: + op = PictOpOverReverse; + break; + } + } + if (color->alpha <= 0x00ff) { + switch (op) { + case PictOpOver: + case PictOpOutReverse: + return; + case PictOpInReverse: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOut; + break; + case PictOpXor: + op = PictOpOverReverse; + break; + } + } else if (color->alpha >= 0xff00) { + switch (op) { + case PictOpOver: + op = PictOpSrc; + break; + case PictOpInReverse: + return; + case PictOpOutReverse: + op = PictOpClear; + break; + case PictOpAtopReverse: + op = PictOpOverReverse; + break; + case PictOpXor: + op = PictOpOut; + break; + } + } + DEBUGF("%s: converted to op %d\n", __FUNCTION__, op); + + if (!_pixman_region_init_clipped_rectangles(®ion, + num_rects, rects, + dst->pDrawable->x, + dst->pDrawable->y, + &dst->pCompositeClip->extents)) + { + DEBUGF("%s: allocation failed for region\n", __FUNCTION__); + return; + } + + need_free_region = TRUE; + + DEBUGF("%s: drawable extents (%d, %d),(%d, %d) x %d\n", + __FUNCTION__, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, + RegionNumRects(®ion)); + + if (dst->pCompositeClip->data && + (!pixman_region_intersect(®ion, ®ion, dst->pCompositeClip) || + region_is_empty(®ion))) { + DEBUGF(("%s: zero-intersection between rectangles and clip\n", + __FUNCTION__)); + pixman_region_fini(®ion); + return; + } + + DEBUGF("%s: clipped extents (%d, %d),(%d, %d) x %d\n", + __FUNCTION__, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2, + RegionNumRects(®ion)); + + glamor_get_drawable_deltas(dst->pDrawable, pixmap, &dst_x, &dst_y); + pixman_region_translate(®ion, dst_x, dst_y); + + DEBUGF("%s: pixmap +(%d, %d) extents (%d, %d),(%d, %d)\n", + __FUNCTION__, dst_x, dst_y, + RegionExtents(®ion)->x1, RegionExtents(®ion)->y1, + RegionExtents(®ion)->x2, RegionExtents(®ion)->y2); + + + boxes = pixman_region_rectangles(®ion, &num_boxes); + if (op == PictOpSrc || op == PictOpClear) { + CARD32 pixel; + if (op == PictOpClear) + pixel = 0; + else + miRenderColorToPixel(dst->pFormat, color, &pixel); + glamor_solid_boxes(pixmap, boxes, num_boxes, pixel); + + goto done; + } else { + if (likely(priv->type != GLAMOR_TEXTURE_LARGE)) { + int error; + + source = CreateSolidPicture(0, color, &error); + if (!source) + goto done; + if (glamor_composite_clipped_region(op, source, + NULL, dst, + NULL, NULL, priv, + ®ion, + 0,0,0,0,0,0)) + goto done; + } + } +fallback: + miCompositeRects(op, dst, color, num_rects, rects); +done: + /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must + * manually append the damaged regions ourselves. + */ + DamageRegionAppend(&pixmap->drawable, ®ion); + DamageRegionProcessPending(&pixmap->drawable); + + if (need_free_region) + pixman_region_fini(®ion); + if (source) + FreePicture(source, 0); + return; +} diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index e37114879..2163c9461 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -180,6 +180,87 @@ glamor_fini_solid_shader(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } +static void +_glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(pixmap); + glamor_gl_dispatch *dispatch; + GLfloat xscale, yscale; + float vertices[32]; + float *pvertices = vertices; + int valid_nbox = ARRAY_SIZE(vertices); + + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glUseProgram(glamor_priv->solid_prog); + + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, color); + + pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); + + if (unlikely(nbox*4*2 > ARRAY_SIZE(vertices))) { + int allocated_box; + + if (nbox * 6 > GLAMOR_COMPOSITE_VBO_VERT_CNT) { + allocated_box = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6; + } else + allocated_box = nbox; + pvertices = malloc(allocated_box * 4 * 2 * sizeof(float)); + if (pvertices) + valid_nbox = allocated_box; + else { + pvertices = vertices; + valid_nbox = ARRAY_SIZE(vertices) / (4*2); + } + } + +#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 + if (unlikely(nbox > 1)) + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + pvertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + + while(nbox) { + int box_cnt, i; + float *valid_vertices; + valid_vertices = pvertices; + box_cnt = nbox > valid_nbox ? valid_nbox : nbox; + for (i = 0; i < box_cnt; i++) { + glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, + box[i].x1, box[i].y1, + box[i].x2, box[i].y2, + glamor_priv->yInverted, + valid_vertices); + valid_vertices += 4*2; + } + if (box_cnt == 1) + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4); + else + dispatch->glDrawElements(GL_TRIANGLES, + box_cnt * 6, + GL_UNSIGNED_SHORT, + NULL); + nbox -= box_cnt; + box += box_cnt; + } + + if (pvertices != vertices) + free(pvertices); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); +} + static void _glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, float *color) @@ -221,6 +302,52 @@ _glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_put_dispatch(glamor_priv); } +Bool +glamor_solid_boxes(PixmapPtr pixmap, + BoxPtr box, int nbox, + unsigned long fg_pixel) +{ + glamor_pixmap_private *pixmap_priv; + GLfloat color[4]; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return FALSE; + + glamor_get_rgba_from_pixel(fg_pixel, + &color[0], + &color[1], + &color[2], + &color[3], format_for_pixmap(pixmap)); + + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionRec region; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + int i; + + RegionInitBoxes(®ion, box, nbox); + clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); + for(i = 0; i < n_region; i++) + { + BoxPtr inner_box; + int inner_nbox; + SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); + + inner_box = RegionRects(clipped_regions[i].region); + inner_nbox = RegionNumRects(clipped_regions[i].region); + _glamor_solid_boxes(pixmap, inner_box, inner_nbox, color); + RegionDestroy(clipped_regions[i].region); + } + free(clipped_regions); + RegionUninit(®ion); + } else + _glamor_solid_boxes(pixmap, box, nbox, color); + + return TRUE; +} + Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, @@ -231,7 +358,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, glamor_get_screen_private(screen); glamor_pixmap_private *pixmap_priv; glamor_gl_dispatch *dispatch; - GLfloat color[4]; + BoxRec box; pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -244,63 +371,25 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, return FALSE; } - glamor_get_rgba_from_pixel(fg_pixel, - &color[0], - &color[1], - &color[2], - &color[3], format_for_pixmap(pixmap)); - dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, alu)) { if (alu == GXclear) - color[0] = color[1] = color[2] = color[3] = 0.0; + fg_pixel = 0; else { glamor_fallback("unsupported alu %x\n", alu); glamor_put_dispatch(glamor_priv); return FALSE; } } - - if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - RegionRec region; - BoxRec box; - int n_region; - glamor_pixmap_clipped_regions *clipped_regions; - int i,j; - - box.x1 = x; - box.y1 = y; - box.x2 = x + width; - box.y2 = y + height; - RegionInitBoxes(®ion, &box, 1); - clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); - for(i = 0; i < n_region; i++) - { - BoxPtr boxes; - int nbox; - SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); - - boxes = RegionRects(clipped_regions[i].region); - nbox = RegionNumRects(clipped_regions[i].region); - for(j = 0; j < nbox; j++) - { - _glamor_solid(pixmap, boxes[j].x1, boxes[j].y1, - boxes[j].x2 - boxes[j].x1, - boxes[j].y2 - boxes[j].y1, color); - } - RegionDestroy(clipped_regions[i].region); - } - free(clipped_regions); - RegionUninit(®ion); - } else - _glamor_solid(pixmap, - x, - y, - width, height, - color); + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + glamor_solid_boxes(pixmap, &box, 1, fg_pixel); glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); return TRUE; } + diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 61551df0b..a7d4fe783 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -210,6 +210,7 @@ struct glamor_saved_procs { GetSpansProcPtr get_spans; GetImageProcPtr get_image; CompositeProcPtr composite; + CompositeRectsProcPtr composite_rects; TrapezoidsProcPtr trapezoids; GlyphsProcPtr glyphs; ChangeWindowAttributesProcPtr change_window_attributes; @@ -644,8 +645,10 @@ Bool glamor_fill(DrawablePtr drawable, Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, unsigned long fg_pixel); -void glamor_solid_fail_region(PixmapPtr pixmap, - int x, int y, int width, int height); +Bool +glamor_solid_boxes(PixmapPtr pixmap, + BoxPtr box, int nbox, + unsigned long fg_pixel); /* glamor_fillspans.c */ void glamor_fill_spans(DrawablePtr drawable, @@ -988,6 +991,13 @@ void glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt); +void +glamor_composite_rectangles(CARD8 op, + PicturePtr dst, + xRenderColor *color, + int num_rects, + xRectangle *rects); + #include"glamor_utils.h" /* Dynamic pixmap upload to texture if needed. diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 88c66168a..a2829855f 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -792,6 +792,12 @@ glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy) } } +static inline Bool +region_is_empty(pixman_region16_t *region) +{ + return region->data && region->data->numRects == 0; +} + #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)) From 0706423bcfd7a589bab3b41fe9f13d0b636ecdef Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 3 Jul 2012 18:11:12 +0800 Subject: [PATCH 414/462] glamor_glyphs: Use cache picture to store mask picture if possible. By default, mask picture is newly created, and each time we need to clear the whole mask picture, and then composite glyphs to the mask picture and then composite the mask picture to destination. Testing results shows that the filling of the mask picture takes a big portion of the rendering time. As we don't really need to clear the whole region, we just need to clear the real overlapped region. This commit is to solve this issue. We split a large glyphs list to serval lists and each list is non-overlapped or overlapped. we can reduce the length of overlapped glyphs to do the glyphs_via_mask to 2 or 3 glyphs one time for most cases. Thus it give us a case to allocate a small portion of the corresponding cache directly as the mask picture. Then we can rendering the glyphs to this mask picture, and latter we can accumulate the second steps, composite the mask to the dest with the other non-overlapped glyphs's rendering process. It also make us implement a batch mask cache blocks clearing algorithm to avoid too frequently small region clearing. If there is no any overlapping, this method will not get performance gain. If there is some overlapping, then this algorithm can get about 15% performance gain. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 1045 +++++++++++++++++++++++++++++++--------- 1 file changed, 830 insertions(+), 215 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index c2a750d07..f63feac77 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -64,8 +64,11 @@ #define CACHE_PICTURE_SIZE 1024 #define GLYPH_MIN_SIZE 8 -#define GLYPH_MAX_SIZE 64 -#define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) +#define GLYPH_MAX_SIZE 64 +#define GLYPH_CACHE_SIZE ((CACHE_PICTURE_SIZE) * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE)) +#define MASK_CACHE_MAX_SIZE 32 +#define MASK_CACHE_WIDTH (CACHE_PICTURE_SIZE / MASK_CACHE_MAX_SIZE) +#define MASK_CACHE_MASK ((1LL << (MASK_CACHE_WIDTH)) - 1) typedef struct { PicturePtr source; @@ -78,7 +81,7 @@ struct glamor_glyph { uint16_t x, y; uint16_t size, pos; unsigned long long left_x1_map, left_x2_map; - unsigned long long right_x1_map, right_x2_map; /* Use to check real pixel overlap or not. */ + unsigned long long right_x1_map, right_x2_map; /* Use to check real intersect or not. */ Bool has_edge_map; Bool cached; }; @@ -89,8 +92,6 @@ typedef enum { GLAMOR_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */ } glamor_glyph_cache_result_t; - - #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) static DevPrivateKeyRec glamor_glyph_key; @@ -100,6 +101,163 @@ glamor_glyph_get_private(GlyphPtr glyph) return (struct glamor_glyph*)glyph->devPrivates; } +/* + * Mask cache is located at the corresponding cache picture's last row. + * and is deadicated for the mask picture when do the glyphs_via_mask. + * + * As we split the glyphs list according to its overlapped or non-overlapped, + * we can reduce the length of glyphs to do the glyphs_via_mask to 2 or 3 + * glyphs one time for most cases. Thus it give us a case to allocate a + * small portion of the corresponding cache directly as the mask picture. + * Then we can rendering the glyphs to this mask picture, and latter we + * can accumulate the second steps, composite the mask to the dest with + * the other non-overlapped glyphs's rendering process. + * Another major benefit is we now only need to clear a relatively small mask + * region then before. It also make us implement a bunch mask picture clearing + * algorithm to avoid too frequently small region clearing. + * + * If there is no any overlapping, this method will not get performance gain. + * If there is some overlapping, then this algorithm can get about 15% performance + * gain. + */ + +struct glamor_glyph_mask_cache_entry { + int idx; + int width; + int height; + int x; + int y; +}; + +static struct glamor_glyph_mask_cache { + PixmapPtr pixmap; + struct glamor_glyph_mask_cache_entry mcache[MASK_CACHE_WIDTH]; + unsigned int free_bitmap; + unsigned int cleared_bitmap; +}*mask_cache[GLAMOR_NUM_GLYPH_CACHE_FORMATS] = {NULL}; + +static void +clear_mask_cache_bitmap(struct glamor_glyph_mask_cache *maskcache, + unsigned int clear_mask_bits) +{ + unsigned int i = 0; + BoxRec box[MASK_CACHE_WIDTH]; + int box_cnt = 0; + + assert((clear_mask_bits & ~MASK_CACHE_MASK) == 0); + for(i = 0; i < MASK_CACHE_WIDTH;i++) + { + if (clear_mask_bits & (1 << i)) { + box[box_cnt].x1 = maskcache->mcache[i].x; + box[box_cnt].x2 = maskcache->mcache[i].x + MASK_CACHE_MAX_SIZE; + box[box_cnt].y1 = maskcache->mcache[i].y; + box[box_cnt].y2 = maskcache->mcache[i].y + MASK_CACHE_MAX_SIZE; + box_cnt++; + } + } + glamor_solid_boxes(maskcache->pixmap, box, box_cnt, 0); + maskcache->cleared_bitmap |= clear_mask_bits; +} + +static void +clear_mask_cache(struct glamor_glyph_mask_cache *maskcache) +{ + int x = 0; + int cnt = MASK_CACHE_WIDTH; + unsigned int i = 0; + struct glamor_glyph_mask_cache_entry *mce; + glamor_solid(maskcache->pixmap, 0, CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, + MASK_CACHE_MAX_SIZE, GXcopy, 0xFFFFFFFF, 0); + mce = &maskcache->mcache[0]; + while(cnt--) { + mce->width = 0; + mce->height = 0; + mce->x = x; + mce->y = CACHE_PICTURE_SIZE; + mce->idx = i++; + x += MASK_CACHE_MAX_SIZE; + mce++; + } + maskcache->free_bitmap = MASK_CACHE_MASK; + maskcache->cleared_bitmap = MASK_CACHE_MASK; +} + +static int +find_continuous_bits(unsigned int bits, int bits_cnt, unsigned int *pbits_mask) +{ + int idx = 0; + unsigned int bits_mask; + bits_mask = ((1LL << bits_cnt) - 1); + + if (unlikely(bits_cnt > 56)) { + while(bits) { + if ((bits & bits_mask) == bits_mask) { + *pbits_mask = bits_mask << idx; + return idx; + } + bits >>= 1; + idx++; + } + } else { + idx = __fls(bits); + while(bits) { + unsigned int temp_bits; + temp_bits = bits_mask << (idx - bits_cnt + 1); + if ((bits & temp_bits) == temp_bits) { + *pbits_mask = temp_bits; + return (idx - bits_cnt + 1); + } + /* Find first zero. And clear the tested bit.*/ + bits &= ~(1LL<free_bitmap == 0) + return NULL; +retry: + free_cleared_bit = maskcache->free_bitmap & maskcache->cleared_bitmap; + if (free_cleared_bit && blocks == 1) { + idx = __fls(free_cleared_bit); + bits_mask = 1 << idx; + } else if (free_cleared_bit && blocks > 1) { + idx = find_continuous_bits(free_cleared_bit, blocks, &bits_mask); + } + + if (idx < 0) { + clear_mask_cache_bitmap(maskcache, maskcache->free_bitmap); + if (retry_cnt++ > 2) + return NULL; + goto retry; + } + + maskcache->cleared_bitmap &= ~bits_mask; + maskcache->free_bitmap &= ~bits_mask; + DEBUGF("get idx %d free %x clear %x \n", + idx, maskcache->free_bitmap, maskcache->cleared_bitmap); + return &maskcache->mcache[idx]; +} + +static void +put_mask_cache_bitmap(struct glamor_glyph_mask_cache *maskcache, + unsigned int bitmap) +{ + maskcache->free_bitmap |= bitmap; + DEBUGF("put bitmap %x free %x clear %x \n", + bitmap, maskcache->free_bitmap, maskcache->cleared_bitmap); +} + static void glamor_unrealize_glyph_caches(ScreenPtr pScreen) { @@ -117,6 +275,9 @@ glamor_unrealize_glyph_caches(ScreenPtr pScreen) if (cache->glyphs) free(cache->glyphs); + + if (mask_cache[i]) + free(mask_cache[i]); } glamor->glyph_cache_initialized = FALSE; } @@ -136,6 +297,7 @@ glamor_glyphs_fini(ScreenPtr pScreen) * This function allocates the storage pixmap, and then fills in the * rest of the allocated structures for all caches with the given format. */ + static Bool glamor_realize_glyph_caches(ScreenPtr pScreen) { @@ -167,7 +329,7 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) /* Now allocate the pixmap and picture */ pixmap = pScreen->CreatePixmap(pScreen, CACHE_PICTURE_SIZE, - CACHE_PICTURE_SIZE, depth, + CACHE_PICTURE_SIZE + MASK_CACHE_MAX_SIZE, depth, 0); if (!pixmap) goto bail; @@ -189,6 +351,9 @@ glamor_realize_glyph_caches(ScreenPtr pScreen) goto bail; cache->evict = rand() % GLYPH_CACHE_SIZE; + mask_cache[i] = calloc(1, sizeof(*mask_cache[i])); + mask_cache[i]->pixmap = pixmap; + clear_mask_cache(mask_cache[i]); } assert(i == GLAMOR_NUM_GLYPH_CACHE_FORMATS); @@ -422,43 +587,166 @@ glamor_glyph_priv_get_edge_map(GlyphPtr glyph, struct glamor_glyph *priv, return; } - - /** * Returns TRUE if the glyphs in the lists intersect. Only checks based on * bounding box, which appears to be good enough to catch most cases at least. */ + +#define INTERSECTED_TYPE_MASK 1 +#define NON_INTERSECTED 0 +#define INTERSECTED 1 + +struct glamor_glyph_list { + int nlist; + GlyphListPtr list; + GlyphPtr *glyphs; + int type; +}; + static Bool +glyph_new_fixed_list(struct glamor_glyph_list *fixed_list, + GlyphPtr *cur_glyphs, + GlyphPtr **head_glyphs, + GlyphListPtr cur_list, + int cur_pos, int cur_x, int cur_y, + int x1, int y1, int x2, int y2, + GlyphListPtr *head_list, + int *head_pos, + int *head_x, + int *head_y, + int *fixed_cnt, + int type, + GlyphListPtr prev_list, + BoxPtr prev_extents + ) +{ + int x_off = 0; + int y_off = 0; + int n_off = 0; + int list_cnt; + if (type == NON_INTERSECTED) { + if (x1 < prev_extents->x2 && x2 > prev_extents->x1 + && y1 < prev_extents->y2 && y2 > prev_extents->y1) + return FALSE; + x_off = (*(cur_glyphs-1))->info.xOff; + y_off = (*(cur_glyphs-1))->info.yOff; + n_off = 1; + } + + list_cnt = cur_list - *head_list + 1; + if (cur_pos <= n_off) { + DEBUGF("break at %d n_off %d\n", cur_pos, n_off); + list_cnt--; + if (cur_pos < n_off) { + /* we overlap with previous list's last glyph. */ + x_off += cur_list->xOff; + y_off += cur_list->yOff; + cur_list--; + cur_pos = cur_list->len; + if (cur_pos <= n_off) { + list_cnt--; + } + } + } + DEBUGF("got %d lists\n", list_cnt); + if (list_cnt != 0) { + fixed_list->list = malloc(list_cnt * sizeof(*cur_list)); + memcpy(fixed_list->list, *head_list, list_cnt * sizeof(*cur_list)); + fixed_list->list[0].xOff = *head_x; + fixed_list->list[0].yOff = *head_y; + fixed_list->glyphs = *head_glyphs; + fixed_list->type = type & INTERSECTED_TYPE_MASK; + fixed_list->nlist = list_cnt; + if (cur_list != *head_list) { + fixed_list->list[0].len = (*head_list)->len - *head_pos; + if (cur_pos != n_off) + fixed_list->list[list_cnt - 1].len = cur_pos - n_off; + } else + fixed_list->list[0].len = cur_pos - *head_pos - n_off; + while(list_cnt--) { + DEBUGF("new fixed list type %d entry len %d x %d y %d" + "head_pos %d pos %d list %d has %d glyphs.\n", + fixed_list->type, fixed_list->nlist, + cur_x, cur_y, *head_pos, cur_pos, i, fixed_list->list[i++].len); + } + (*fixed_cnt)++; + } + + if (type <= INTERSECTED) { + *head_list = cur_list; + *head_pos = cur_pos - n_off; + *head_x = cur_x - x_off; + *head_y = cur_y - y_off; + *head_glyphs = cur_glyphs - n_off; + } + return TRUE; +} + +/* + * This function detects glyph lists's overlapping. + * + * If check_fake_overlap is set, then it will check the glyph's left + * and right small boxes's real overlapping pixels. And if there is + * no real pixel overlapping, then it will not be treated as overlapped + * case. And we also can configured it to ignore less than 2 pixels + * overlappig. + * + * This function analyzes all the lists and split the list to multiple + * lists which are pure overlapped glyph lists or pure non-overlapped + * list if the overlapping only ocurr on the two adjacent glyphs. + * Otherwise, it return -1. + * + **/ + +static int glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, PictFormatShort mask_format, - ScreenPtr screen, Bool check_fake_overlap) + ScreenPtr screen, Bool check_fake_overlap, + struct glamor_glyph_list * fixed_list, + int fixed_size) { int x1, x2, y1, y2; int n; int x, y; - BoxRec extents; + BoxRec extents, prev_extents; Bool first = TRUE; + Bool need_free_fixed_list = FALSE; struct glamor_glyph *priv; + Bool in_non_intersected_list = -1; + GlyphListPtr head_list, prev_list, saved_list; + int head_x, head_y, head_pos; + int fixed_cnt = 0; + GlyphPtr *head_glyphs; + GlyphListPtr cur_list = list; + saved_list = list; x = 0; y = 0; extents.x1 = 0; extents.y1 = 0; extents.x2 = 0; extents.y2 = 0; + prev_extents = extents; + prev_list = list; + head_list = list; + DEBUGF("has %d lists.\n", nlist); while (nlist--) { BoxRec left_box, right_box; Bool has_left_edge_box = FALSE, has_right_edge_box = FALSE; - Bool left_to_right = TRUE; + Bool left_to_right; struct glamor_glyph *left_priv, *right_priv; x += list->xOff; y += list->yOff; n = list->len; - list++; + left_to_right = TRUE; + cur_list = list++; + + DEBUGF("current list %p has %d glyphs\n", cur_list, n); while (n--) { GlyphPtr glyph = *glyphs++; + DEBUGF("the %dth glyph\n", cur_list->len - n - 1); if (glyph->info.width == 0 || glyph->info.height == 0) { x += glyph->info.xOff; @@ -466,8 +754,11 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, continue; } if (mask_format - && mask_format != GlyphPicture(glyph)[screen->myNum]->format) - return TRUE; + && mask_format != GlyphPicture(glyph)[screen->myNum]->format) { + need_free_fixed_list = TRUE; + goto done; + } + x1 = x - glyph->info.x; if (x1 < MINSHORT) x1 = MINSHORT; @@ -476,6 +767,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, y1 = MINSHORT; if (check_fake_overlap) priv = glamor_glyph_get_private(glyph); + x2 = x1 + glyph->info.width; y2 = y1 + glyph->info.height; @@ -490,6 +782,12 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, extents.x2 = x2; extents.y2 = y2; + first = FALSE; + head_list = cur_list; + head_pos = cur_list->len - n - 1; + head_x = x; + head_y = y; + head_glyphs = glyphs - 1; if (check_fake_overlap && priv && priv->has_edge_map && glyph->info.yOff == 0) { left_box.x1 = x1; @@ -503,30 +801,28 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, has_left_edge_box = TRUE; has_right_edge_box = TRUE; } - - first = FALSE; } else { if (x1 < extents.x2 && x2 > extents.x1 && y1 < extents.y2 && y2 > extents.y1) { - if (check_fake_overlap && priv + + if (check_fake_overlap && (has_left_edge_box || has_right_edge_box) && priv->has_edge_map && glyph->info.yOff == 0) { int left_dx, right_dx; unsigned long long intersected; left_dx = has_left_edge_box ? 1 : 0; right_dx = has_right_edge_box ? 1 : 0; - if (x1 + 1 < extents.x2 - right_dx && x2 - 1 > extents.x1 + left_dx) - return TRUE; + goto real_intersected; if (left_to_right && has_right_edge_box) { if (x1 == right_box.x1) { intersected = ((priv->left_x1_map & right_priv->right_x1_map) | (priv->left_x2_map & right_priv->right_x2_map)); if (intersected) - return TRUE; + goto real_intersected; } else if (x1 == right_box.x2) { intersected = (priv->left_x1_map & right_priv->right_x2_map); if (intersected) { @@ -535,7 +831,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, intersected &= ~(1<<__fls(intersected)); if ((intersected & (intersected - 1))) #endif - return TRUE; + goto real_intersected; } } } else if (!left_to_right && has_left_edge_box) { @@ -547,20 +843,77 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, intersected &= ~(1<<__fls(intersected)); if ((intersected & (intersected - 1))) #endif - return TRUE; + goto real_intersected; } } else if (x2 - 1 == right_box.x2) { if ((priv->right_x1_map & left_priv->left_x1_map) || (priv->right_x2_map & left_priv->left_x2_map)) - return TRUE; + goto real_intersected; } } else { if (x1 < extents.x2 && x1 + 2 > extents.x1) - return TRUE; + goto real_intersected; } - } else - return TRUE; + goto non_intersected; + } else { +real_intersected: + DEBUGF("overlap with previous glyph.\n"); + if (in_non_intersected_list == 1) { + if (fixed_cnt >= fixed_size) { + need_free_fixed_list = TRUE; + goto done; + } + if (!glyph_new_fixed_list(&fixed_list[fixed_cnt], + glyphs - 1, + &head_glyphs, + cur_list, + cur_list->len - (n + 1), x, y, + x1, y1, x2, y2, + &head_list, + &head_pos, + &head_x, + &head_y, &fixed_cnt, + NON_INTERSECTED, + prev_list, + &prev_extents + )){ + need_free_fixed_list = TRUE; + goto done; + } + } + + in_non_intersected_list = 0; + + } + } else { +non_intersected: + DEBUGF("doesn't overlap with previous glyph.\n"); + if (in_non_intersected_list == 0) { + if (fixed_cnt >= fixed_size) { + need_free_fixed_list = TRUE; + goto done; + } + if (!glyph_new_fixed_list(&fixed_list[fixed_cnt], + glyphs - 1, + &head_glyphs, + cur_list, + cur_list->len - (n + 1), x, y, + x1, y1, x2, y2, + &head_list, + &head_pos, + &head_x, + &head_y, &fixed_cnt, + INTERSECTED, + prev_list, + &prev_extents + )) { + need_free_fixed_list = TRUE; + goto done; + } + } + in_non_intersected_list = 1; } + prev_extents = extents; } if (check_fake_overlap && priv @@ -571,11 +924,11 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, left_box.y1 = y1; has_left_edge_box = TRUE; left_priv = priv; - } + } - if (!has_right_edge_box || x2 > extents.x2) { - right_box.x1 = x2 - 2; - right_box.x2 = x2 - 1; + if (!has_right_edge_box || x2 > extents.x2) { + right_box.x1 = x2 - 2; + right_box.x2 = x2 - 1; right_box.y1 = y1; has_right_edge_box = TRUE; right_priv = priv; @@ -594,10 +947,49 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, x += glyph->info.xOff; y += glyph->info.yOff; + prev_list = cur_list; } } - return FALSE; + if (in_non_intersected_list == 0 && fixed_cnt == 0) { + fixed_cnt = -1; + goto done; + } + + if ((in_non_intersected_list != -1 + || head_pos != n) && (fixed_cnt > 0)) { + if (fixed_cnt >= fixed_size) { + need_free_fixed_list = TRUE; + goto done; + } + if (!glyph_new_fixed_list(&fixed_list[fixed_cnt], + glyphs - 1, + &head_glyphs, + cur_list, + cur_list->len - (n + 1), x, y, + x1, y1, x2, y2, + &head_list, + &head_pos, + &head_x, + &head_y, &fixed_cnt, + (!in_non_intersected_list) | 0x80, + prev_list, + &prev_extents + )) { + need_free_fixed_list = TRUE; + goto done; + } + } + +done: + if (need_free_fixed_list && fixed_cnt >= 0) { + while(fixed_cnt--) { + free(fixed_list[fixed_cnt].list); + } + } + + DEBUGF("Got %d fixed list \n", fixed_cnt); + return fixed_cnt; } static inline unsigned int @@ -690,6 +1082,7 @@ glamor_glyph_cache(glamor_screen_private *glamor, GlyphPtr glyph, int *out_x, cache->evict = rand() % GLYPH_CACHE_SIZE; } + cache->glyphs[pos] = glyph; priv->cache = cache; @@ -722,29 +1115,95 @@ glamor_glyph_cache(glamor_screen_private *glamor, GlyphPtr glyph, int *out_x, return cache->picture; } typedef void (*glyphs_flush)(void * arg); +struct glyphs_flush_dst_arg { + CARD8 op; + PicturePtr src; + PicturePtr dst; + glamor_glyph_buffer_t * buffer; + int x_src,y_src; + int x_dst, y_dst; +}; + +static struct glyphs_flush_dst_arg dst_arg; +static struct glyphs_flush_mask_arg mask_arg; +static glamor_glyph_buffer_t dst_buffer; +static glamor_glyph_buffer_t mask_buffer; +unsigned long long mask_glyphs_cnt = 0; +unsigned long long dst_glyphs_cnt = 0; +#define GLYPHS_DST_MODE_VIA_MASK 0 +#define GLYPHS_DST_MODE_VIA_MASK_CACHE 1 +#define GLYPHS_DST_MODE_TO_DST 2 +#define GLYPHS_DST_MODE_MASK_TO_DST 3 + +struct glyphs_flush_mask_arg { + PicturePtr mask; + glamor_glyph_buffer_t *buffer; + struct glamor_glyph_mask_cache *maskcache; + unsigned int used_bitmap; +}; + +static void +glamor_glyphs_flush_mask(struct glyphs_flush_mask_arg *arg) +{ + if (arg->buffer->count>0) { +#ifdef RENDER + glamor_composite_glyph_rects(PictOpAdd, arg->buffer->source, + NULL, arg->mask, + arg->buffer->count, + arg->buffer->rects); +#endif + } + arg->buffer->count = 0; + arg->buffer->source = NULL; + +} + +static void +glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg * arg) +{ + if (mask_buffer.count > 0) { + glamor_glyphs_flush_mask(&mask_arg); + } + if (mask_arg.used_bitmap) { + put_mask_cache_bitmap(mask_arg.maskcache, mask_arg.used_bitmap); + mask_arg.used_bitmap = 0; + } + + if (arg->buffer->count > 0) { + glamor_composite_glyph_rects(arg->op, arg->src, + arg->buffer->source, arg->dst, + arg->buffer->count, + &arg->buffer->rects[0]); + arg->buffer->count = 0; + arg->buffer->source = NULL; + } +} + static glamor_glyph_cache_result_t glamor_buffer_glyph(glamor_screen_private *glamor_priv, glamor_glyph_buffer_t * buffer, - GlyphPtr glyph, int x_glyph, int y_glyph, + PictFormatShort format, + GlyphPtr glyph, struct glamor_glyph *priv, + int x_glyph, int y_glyph, int dx, int dy, int w, int h, + int glyphs_dst_mode, glyphs_flush glyphs_flush, void *flush_arg) { ScreenPtr screen = glamor_priv->screen; - unsigned int format = (GlyphPicture(glyph)[screen->myNum])->format; glamor_composite_rect_t *rect; PicturePtr source; - struct glamor_glyph *priv; int x, y; - PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum]; glamor_glyph_cache_t *cache; + if (glyphs_dst_mode != GLYPHS_DST_MODE_MASK_TO_DST) + priv = glamor_glyph_get_private(glyph); + if (PICT_FORMAT_BPP(format) == 1) format = PICT_a8; cache = - &glamor_priv->glyphCaches[PICT_FORMAT_RGB - (glyph_picture->format) != 0]; + &glamor_priv->glyphCaches[PICT_FORMAT_RGB(format) != 0]; if (buffer->source && buffer->source != cache->picture @@ -759,25 +1218,36 @@ glamor_buffer_glyph(glamor_screen_private *glamor_priv, glyphs_flush = NULL; } - priv = glamor_glyph_get_private(glyph); - if (priv && priv->cached) { rect = &buffer->rects[buffer->count++]; rect->x_src = priv->x + dx; rect->y_src = priv->y + dy; if (buffer->source == NULL) buffer->source = priv->cache->picture; - assert(priv->cache->glyphs[priv->pos] == glyph); + if (glyphs_dst_mode <= GLYPHS_DST_MODE_VIA_MASK_CACHE) + assert(priv->cache->glyphs[priv->pos] == glyph); } else { + assert(glyphs_dst_mode != GLYPHS_DST_MODE_MASK_TO_DST); if (glyphs_flush) (*glyphs_flush)(flush_arg); source = glamor_glyph_cache(glamor_priv, glyph, &x, &y); + if (source != NULL) { rect = &buffer->rects[buffer->count++]; rect->x_src = x + dx; rect->y_src = y + dy; if (buffer->source == NULL) buffer->source = source; + if (glyphs_dst_mode == GLYPHS_DST_MODE_VIA_MASK_CACHE) { + glamor_gl_dispatch *dispatch; + /* mode 1 means we are using global mask cache, + * thus we have to composite from the cache picture + * to the cache picture, we need a flush here to make + * sure latter we get the corret glyphs data.*/ + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glFlush(); + glamor_put_dispatch(glamor_priv); + } } else { /* Couldn't find the glyph in the cache, use the glyph picture directly */ source = GlyphPicture(glyph)[screen->myNum]; @@ -794,31 +1264,78 @@ glamor_buffer_glyph(glamor_screen_private *glamor_priv, priv = glamor_glyph_get_private(glyph); } - rect->x_dst = x_glyph - glyph->info.x; - rect->y_dst = y_glyph - glyph->info.y; + rect->x_dst = x_glyph; + rect->y_dst = y_glyph; + if (glyphs_dst_mode != GLYPHS_DST_MODE_MASK_TO_DST) { + rect->x_dst -= glyph->info.x; + rect->y_dst -= glyph->info.y; + } rect->width = w; rect->height = h; + if (glyphs_dst_mode > GLYPHS_DST_MODE_VIA_MASK_CACHE) { + rect->x_mask = rect->x_src; + rect->y_mask = rect->y_src; + rect->x_src = dst_arg.x_src + rect->x_dst - dst_arg.x_dst; + rect->y_src = dst_arg.y_src + rect->y_dst - dst_arg.y_dst; + } + return GLAMOR_GLYPH_SUCCESS; } -struct glyphs_flush_mask_arg { - PicturePtr mask; - glamor_glyph_buffer_t *buffer; -}; static void -glamor_glyphs_flush_mask(struct glyphs_flush_mask_arg *arg) +glamor_buffer_glyph_clip(glamor_screen_private *glamor_priv, + BoxPtr rects, + int nrect, PictFormatShort format, + GlyphPtr glyph, struct glamor_glyph *priv, + int glyph_x, int glyph_y, + int glyph_dx, int glyph_dy, + int width, int height, + int glyphs_mode, + glyphs_flush flush_func, + void *arg + ) { -#ifdef RENDER - glamor_composite_glyph_rects(PictOpAdd, arg->buffer->source, - NULL, arg->mask, - arg->buffer->count, - arg->buffer->rects); -#endif - arg->buffer->count = 0; - arg->buffer->source = NULL; + int i; + for (i = 0; i < nrect; i++) { + int dst_x, dst_y; + int dx, dy; + int x2, y2; + + dst_x = glyph_x - glyph_dx; + dst_y = glyph_y - glyph_dy; + x2 = dst_x + width; + y2 = dst_y + height; + dx = dy = 0; + if (rects[i].y1 >= y2) + break; + + if (dst_x < rects[i].x1) + dx = rects[i].x1 - dst_x, dst_x = rects[i].x1; + if (x2 > rects[i].x2) + x2 = rects[i].x2; + if (dst_y < rects[i].y1) + dy = rects[i].y1 - dst_y, dst_y = rects[i].y1; + if (y2 > rects[i].y2) + y2 = rects[i].y2; + if (dst_x < x2 && dst_y < y2) { + + glamor_buffer_glyph(glamor_priv, + &dst_buffer, + format, + glyph, priv, + dst_x + glyph_dx, + dst_y + glyph_dy, + dx, dy, + x2 - dst_x, y2 - dst_y, + glyphs_mode, + flush_func, + arg); + } + } } + static void glamor_glyphs_via_mask(CARD8 op, PicturePtr src, @@ -826,7 +1343,8 @@ glamor_glyphs_via_mask(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, - int nlist, GlyphListPtr list, GlyphPtr * glyphs) + int nlist, GlyphListPtr list, GlyphPtr * glyphs, + Bool use_mask_cache) { PixmapPtr mask_pixmap = 0; PicturePtr mask; @@ -839,11 +1357,16 @@ glamor_glyphs_via_mask(CARD8 op, int error; BoxRec extents = { 0, 0, 0, 0 }; XID component_alpha; - glamor_glyph_buffer_t buffer; - xRectangle fill_rect; - struct glyphs_flush_mask_arg arg; - GCPtr gc; glamor_screen_private *glamor_priv; + int need_free_mask = FALSE; + glamor_glyph_buffer_t buffer; + struct glyphs_flush_mask_arg arg; + glamor_glyph_buffer_t *pmask_buffer; + struct glyphs_flush_mask_arg *pmask_arg; + struct glamor_glyph_mask_cache_entry *mce = NULL; + struct glamor_glyph_mask_cache *maskcache; + glamor_glyph_cache_t *cache; + int glyphs_dst_mode; glamor_glyph_extents(nlist, list, glyphs, &extents); @@ -861,113 +1384,173 @@ glamor_glyphs_via_mask(CARD8 op, mask_format = a8Format; } - mask_pixmap = screen->CreatePixmap(screen, width, height, - mask_format->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!mask_pixmap) - return; - component_alpha = NeedsComponent(mask_format->format); - mask = CreatePicture(0, &mask_pixmap->drawable, - mask_format, CPComponentAlpha, - &component_alpha, serverClient, &error); - if (!mask) { - screen->DestroyPixmap(mask_pixmap); - return; - } - gc = GetScratchGC(mask_pixmap->drawable.depth, screen); - ValidateGC(&mask_pixmap->drawable, gc); - gc->fillStyle = FillSolid; - //glamor_fill(&mask_pixmap->drawable, gc, 0, 0, width, height, TRUE); - fill_rect.x = 0; - fill_rect.y = 0; - fill_rect.width = width; - fill_rect.height = height; - gc->ops->PolyFillRect(&mask_pixmap->drawable, gc, 1, &fill_rect); - FreeScratchGC(gc); + cache = &glamor_priv->glyphCaches + [PICT_FORMAT_RGB(mask_format->format) != 0]; + maskcache = mask_cache[PICT_FORMAT_RGB(mask_format->format) != 0]; + x = -extents.x1; y = -extents.y1; + if (!use_mask_cache + || width > (CACHE_PICTURE_SIZE/4) + || height > MASK_CACHE_MAX_SIZE) { +new_mask_pixmap: + mask_pixmap = glamor_create_pixmap(screen, width, height, + mask_format->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!mask_pixmap) { + glamor_destroy_pixmap(mask_pixmap); + return; + } + glamor_solid(mask_pixmap, 0, 0, width, height, GXcopy, 0xFFFFFFFF, 0); + component_alpha = NeedsComponent(mask_format->format); + mask = CreatePicture(0, &mask_pixmap->drawable, + mask_format, CPComponentAlpha, + &component_alpha, serverClient, &error); + if (!mask) + return; + need_free_mask = TRUE; + pmask_arg = &arg; + pmask_buffer = &buffer; + pmask_buffer->count = 0; + pmask_buffer->source = NULL; + pmask_arg->used_bitmap = 0; + glyphs_dst_mode = GLYPHS_DST_MODE_VIA_MASK; + } else { + int retry_cnt = 0; +retry: + mce = get_mask_cache(maskcache, + (width + MASK_CACHE_MAX_SIZE - 1) / MASK_CACHE_MAX_SIZE); - buffer.count = 0; - buffer.source = NULL; + if (mce == NULL) { + glamor_glyphs_flush_dst(&dst_arg); + retry_cnt++; + if (retry_cnt > 2) { + assert(0); + goto new_mask_pixmap; + } + goto retry; + } + + mask = cache->picture; + x += mce->x; + y += mce->y; + mce->width = (width + MASK_CACHE_MAX_SIZE - 1) / MASK_CACHE_MAX_SIZE; + mce->height = 1; + if (mask_arg.mask && mask_arg.mask != mask + && mask_buffer.count != 0) + glamor_glyphs_flush_dst(&dst_arg); + pmask_arg = &mask_arg; + pmask_buffer = &mask_buffer; + pmask_arg->maskcache = maskcache; + glyphs_dst_mode = GLYPHS_DST_MODE_VIA_MASK_CACHE; + } + pmask_arg->mask = mask; + pmask_arg->buffer = pmask_buffer; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; + mask_glyphs_cnt += n; while (n--) { glyph = *glyphs++; if (glyph->info.width > 0 && glyph->info.height > 0) { glyphs_flush flush_func; - if (buffer.count) { - arg.mask = mask; - arg.buffer = &buffer; - flush_func = (glyphs_flush)glamor_glyphs_flush_mask; + void *arg; + if (need_free_mask) { + if (pmask_buffer->count) + flush_func = (glyphs_flush)glamor_glyphs_flush_mask; + else + flush_func = NULL; + arg = pmask_arg; + } else { + /* If we are using global mask cache, then we need to + * flush dst instead of mask. As some dst depends on the + * previous mask result. Just flush mask can't get all previous's + * overlapped glyphs.*/ + if (dst_buffer.count || mask_buffer.count) + flush_func = (glyphs_flush)glamor_glyphs_flush_dst; + else + flush_func = NULL; + arg = &dst_arg; } - else - flush_func = NULL; - - glamor_buffer_glyph(glamor_priv, &buffer, - glyph, x, y, + glamor_buffer_glyph(glamor_priv, pmask_buffer, + mask_format->format, + glyph, NULL, x, y, 0, 0, glyph->info.width, glyph->info.height, + glyphs_dst_mode, flush_func, - (void*)&arg); + (void*)arg); } - x += glyph->info.xOff; y += glyph->info.yOff; } list++; } - if (buffer.count) { - arg.mask = mask; - arg.buffer = &buffer; - glamor_glyphs_flush_mask(&arg); - } - x = extents.x1; y = extents.y1; - CompositePicture(op, - src, - mask, - dst, - x_src + x - x_dst, - y_src + y - y_dst, 0, 0, x, y, width, height); - FreePicture(mask, 0); - screen->DestroyPixmap(mask_pixmap); -} + if (need_free_mask) { + glamor_glyphs_flush_mask(pmask_arg); + CompositePicture(op, + src, + mask, + dst, + x_src + x - x_dst, + y_src + y - y_dst, 0, 0, x, y, width, height); + FreePicture(mask, 0); + glamor_destroy_pixmap(mask_pixmap); + } else { + struct glamor_glyph priv; + glyphs_flush flush_func; + BoxPtr rects; + int nrect; -struct glyphs_flush_dst_arg { - CARD8 op; - PicturePtr src; - PicturePtr dst; - glamor_glyph_buffer_t * buffer; - INT16 x_src; - INT16 y_src; - INT16 x_dst; - INT16 y_dst; -}; + priv.cache = cache; + priv.x = mce->x; + priv.y = mce->y; + priv.cached = TRUE; + rects = REGION_RECTS(dst->pCompositeClip); + nrect = REGION_NUM_RECTS(dst->pCompositeClip); -static void -glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg * arg) -{ - int i; - glamor_composite_rect_t *rect = &arg->buffer->rects[0]; - for (i = 0; i < arg->buffer->count; i++, rect++) { - rect->x_mask = rect->x_src; - rect->y_mask = rect->y_src; - rect->x_src = arg->x_src + rect->x_dst - arg->x_dst; - rect->y_src = arg->y_src + rect->y_dst - arg->y_dst; + pmask_arg->used_bitmap |= ((1 << mce->width) - 1) << mce->idx; + dst_arg.op = op; + dst_arg.src = src; + dst_arg.dst = dst; + dst_arg.buffer = &dst_buffer; + dst_arg.x_src = x_src; + dst_arg.y_src = y_src; + dst_arg.x_dst = x_dst; + dst_arg.y_dst = y_dst; + + if (dst_buffer.source == NULL) { + dst_buffer.source = cache->picture; + } else if (dst_buffer.source != cache->picture) { + glamor_glyphs_flush_dst(&dst_arg); + dst_buffer.source = cache->picture; + } + + x += dst->pDrawable->x; + y += dst->pDrawable->y; + + if (dst_buffer.count || mask_buffer.count) + flush_func = (glyphs_flush)glamor_glyphs_flush_dst; + else + flush_func = NULL; + + glamor_buffer_glyph_clip(glamor_priv, + rects, nrect, + mask_format->format, + NULL, &priv, + x, y, + 0, 0, + width, height, + GLYPHS_DST_MODE_MASK_TO_DST, + flush_func, + (void *)&dst_arg + ); } - - glamor_composite_glyph_rects(arg->op, arg->src, - arg->buffer->source, arg->dst, - arg->buffer->count, - &arg->buffer->rects[0]); - - arg->buffer->count = 0; - arg->buffer->source = NULL; } static void @@ -984,82 +1567,54 @@ glamor_glyphs_to_dst(CARD8 op, int x_dst = list->xOff, y_dst = list->yOff; int n; GlyphPtr glyph; - glamor_glyph_buffer_t buffer; - struct glyphs_flush_dst_arg arg; BoxPtr rects; int nrect; glamor_screen_private *glamor_priv; - buffer.count = 0; - buffer.source = NULL; - rects = REGION_RECTS(dst->pCompositeClip); nrect = REGION_NUM_RECTS(dst->pCompositeClip); glamor_priv = glamor_get_screen_private(screen); - arg.op = op; - arg.src = src; - arg.dst = dst; - arg.buffer = &buffer; - arg.x_src = x_src; - arg.y_src = y_src; - arg.x_dst = x_dst; - arg.y_dst = y_dst; + dst_arg.op = op; + dst_arg.src = src; + dst_arg.dst = dst; + dst_arg.buffer = &dst_buffer; + dst_arg.x_src = x_src; + dst_arg.y_src = y_src; + dst_arg.x_dst = x_dst; + dst_arg.y_dst = y_dst; + x = dst->pDrawable->x; + y = dst->pDrawable->y; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; + dst_glyphs_cnt += n; while (n--) { - int i; glyph = *glyphs++; if (glyph->info.width > 0 && glyph->info.height > 0) { glyphs_flush flush_func; - if (buffer.count) + if (dst_buffer.count || mask_buffer.count) flush_func = (glyphs_flush)glamor_glyphs_flush_dst; else flush_func = NULL; - - for (i = 0; i < nrect; i++) { - int dst_x, dst_y; - int dx, dy; - int x2, y2; - - dst_x = x - glyph->info.x; - dst_y = y - glyph->info.y; - x2 = dst_x + glyph->info.width; - y2 = dst_y + glyph->info.height; - dx = dy = 0; - if (rects[i].y1 >= y2) - break; - - if (dst_x < rects[i].x1) - dx = rects[i].x1 - dst_x, dst_x = rects[i].x1; - if (x2 > rects[i].x2) - x2 = rects[i].x2; - if (dst_y < rects[i].y1) - dy = rects[i].y1 - dst_y, dst_y = rects[i].y1; - if (y2 > rects[i].y2) - y2 = rects[i].y2; - - if (dst_x < x2 && dst_y < y2) { - - glamor_buffer_glyph(glamor_priv, - &buffer, - glyph, - dst_x + glyph->info.x, - dst_y + glyph->info.y, - dx, dy, - x2 - dst_x, y2 - dst_y, - flush_func, - (void*)&arg); - } - } + glamor_buffer_glyph_clip(glamor_priv, + rects, nrect, + (GlyphPicture(glyph)[screen->myNum])->format, + glyph, NULL, + x, y, + glyph->info.x, glyph->info.y, + glyph->info.width, glyph->info.height, + GLYPHS_DST_MODE_TO_DST, + flush_func, + (void *)&dst_arg + ); } x += glyph->info.xOff; @@ -1067,9 +1622,13 @@ glamor_glyphs_to_dst(CARD8 op, } list++; } - - if (buffer.count) - glamor_glyphs_flush_dst(&arg); +} +#define MAX_FIXED_SIZE +static void +glamor_glyphs_reset_buffer(glamor_glyph_buffer_t *buffer) +{ + buffer->count = 0; + buffer->source = NULL; } static Bool @@ -1081,8 +1640,10 @@ _glamor_glyphs(CARD8 op, INT16 y_src, int nlist, GlyphListPtr list, GlyphPtr * glyphs, Bool fallback) { - Bool intersected = FALSE; PictFormatShort format; + int fixed_size, fixed_cnt = 0; + struct glamor_glyph_list *fixed_list = NULL; + Bool need_free_list = FALSE; #ifndef GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK Bool check_fake_overlap = TRUE; if (!(op == PictOpOver @@ -1098,39 +1659,93 @@ _glamor_glyphs(CARD8 op, #else Bool check_fake_overlap = FALSE; #endif - - if (!mask_format || (((nlist == 1 && list->len == 1) || op == PictOpAdd) - && (dst->format == ((mask_format->depth << 24) | mask_format->format)))) { - glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, - list, glyphs); - return TRUE; - } - if (mask_format) format = mask_format->depth << 24 | mask_format->format; else format = 0; - intersected = glamor_glyphs_intersect(nlist, list, glyphs, - format, dst->pDrawable->pScreen, - check_fake_overlap); + fixed_size = 32; + glamor_glyphs_reset_buffer(&dst_buffer); - if (!intersected) { + if (!mask_format || (((nlist == 1 && list->len == 1) || op == PictOpAdd) + && (dst->format == ((mask_format->depth << 24) | mask_format->format)))) { glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, list, glyphs); - return TRUE; + goto last_flush; } - if (mask_format) - glamor_glyphs_via_mask(op, src, dst, mask_format, - x_src, y_src, nlist, list, glyphs); - else { - /* No mask_format and has intersect and glyphs have different format. - * XXX do we need to implement a new glyphs rendering function for - * this case?*/ - glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, list, glyphs); + glamor_glyphs_reset_buffer(&mask_buffer); + + /* We have mask_format. Need to check the real overlap or not.*/ + format = mask_format->depth << 24 | mask_format->format; + + fixed_list = calloc(fixed_size, sizeof(*fixed_list)); + if (unlikely(fixed_list == NULL)) + fixed_size = 0; + fixed_cnt = glamor_glyphs_intersect(nlist, list, glyphs, + format, dst->pDrawable->pScreen, + check_fake_overlap, + fixed_list, fixed_size); + if (fixed_cnt == 0) + mask_format = NULL; + need_free_list = TRUE; + + if (fixed_cnt <= 0) { + if (mask_format == NULL) { + glamor_glyphs_to_dst(op, src, dst, x_src, y_src, nlist, + list, glyphs); + goto last_flush; + } else { + glamor_glyphs_via_mask(op, src, dst, mask_format, + x_src, y_src, nlist, list, glyphs, + FALSE); + goto free_fixed_list; + } + } else { + + /* We have splitted the original list to serval list, some are overlapped + * and some are non-overlapped. For the non-overlapped, we render it to + * dst directly. For the overlapped, we render it to mask picture firstly, + * then render the mask to dst. If we can use mask cache which is in the + * glyphs cache's last row, we can accumulate the rendering of mask to dst + * with the other dst_buffer's rendering operations thus can reduce the call + * of glDrawElements. + * + * */ + struct glamor_glyph_list *saved_list; + + saved_list = fixed_list; + mask_arg.used_bitmap = 0; + while(fixed_cnt--) { + if (fixed_list->type == NON_INTERSECTED) { + glamor_glyphs_to_dst(op, src, dst, + x_src, y_src, + fixed_list->nlist, + fixed_list->list, + fixed_list->glyphs); + } + else + glamor_glyphs_via_mask(op, src, dst, + mask_format, x_src, y_src, + fixed_list->nlist, + fixed_list->list, + fixed_list->glyphs, TRUE); + + free(fixed_list->list); + fixed_list++; + } + free(saved_list); + need_free_list = FALSE; } +last_flush: + if (dst_buffer.count || mask_buffer.count) + glamor_glyphs_flush_dst(&dst_arg); +free_fixed_list: + if(need_free_list) { + assert(fixed_cnt <= 0); + free(fixed_list); + } return TRUE; } From 32a7438bf79573100862ad91c5722d12623a8bf9 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 3 Jul 2012 18:24:07 +0800 Subject: [PATCH 415/462] glamor_copyarea: Use blitcopy if current state is not render. Practically, for pure 2D blit, the blit copy is much faster than textured copy. For the x11perf copywinwin100, it's about 3x faster. But if we have heavy rendering/compositing, then use textured copy will get much better (>30%)performance for most of the cases. So we simply add a data element to track current state. For rendering state we use textured copy, otherwise, we use blit copy. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 5 +++++ glamor/glamor_copyarea.c | 5 ++++- glamor/glamor_fill.c | 43 ++-------------------------------------- glamor/glamor_priv.h | 8 +++++++- glamor/glamor_render.c | 4 +++- glamor/glamor_tile.c | 3 +++ 6 files changed, 24 insertions(+), 44 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 01f6a9a8f..8b7dc930d 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -225,6 +225,11 @@ glamor_block_handler(ScreenPtr screen) dispatch->glFlush(); glamor_fbo_expire(glamor_priv); glamor_put_dispatch(glamor_priv); + if (glamor_priv->state == RENDER_STATE + && glamor_priv->render_idle_cnt++ > RENDER_IDEL_MAX) { + glamor_priv->state = IDLE_STATE; + glamor_priv->render_idle_cnt = 0; + } } static void diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index ee6f8120f..299417927 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -137,6 +137,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, } } glamor_put_dispatch(glamor_priv); + glamor_priv->state = BLIT_STATE; return TRUE; } #endif @@ -257,6 +258,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch->glUseProgram(0); /* The source texture is bound to a fbo, we have to flush it here. */ glamor_put_dispatch(glamor_priv); + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; return TRUE; } @@ -315,7 +318,7 @@ __glamor_copy_n_to_n(DrawablePtr src, dx, dy, src_pixmap, dst_pixmap); #ifndef GLAMOR_GLES2 - if ((overlaped + if ((overlaped || glamor_priv->state != RENDER_STATE || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 2163c9461..1d81aea52 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -259,47 +259,8 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color) dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); glamor_put_dispatch(glamor_priv); -} - -static void -_glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - float *color) -{ - ScreenPtr screen = pixmap->drawable.pScreen; - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - glamor_pixmap_private *pixmap_priv = - glamor_get_pixmap_private(pixmap); - glamor_gl_dispatch *dispatch; - int x1 = x; - int x2 = x + width; - int y1 = y; - int y2 = y + height; - float vertices[8]; - GLfloat xscale, yscale; - - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glUseProgram(glamor_priv->solid_prog); - - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, - 1, color); - - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); - - glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, - x1, y1, - x2, y2, - glamor_priv->yInverted, vertices); - dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glUseProgram(0); - glamor_put_dispatch(glamor_priv); + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; } Bool diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index a7d4fe783..0703c076d 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -199,7 +199,6 @@ typedef struct { uint16_t evict; } glamor_glyph_cache_t; - #include "glamor_gl_dispatch.h" struct glamor_saved_procs { @@ -235,6 +234,11 @@ struct glamor_saved_procs { #define GLAMOR_TICK_AFTER(t0, t1) \ (((int)(t1) - (int)(t0)) < 0) +#define IDLE_STATE 0 +#define RENDER_STATE 1 +#define BLIT_STATE 2 +#define RENDER_IDEL_MAX 32 + typedef struct glamor_screen_private { struct glamor_gl_dispatch _dispatch; int yInverted; @@ -296,6 +300,8 @@ typedef struct glamor_screen_private { char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; int delayed_fallback_pending; int flags; + int state; + unsigned int render_idle_cnt; ScreenPtr screen; } glamor_screen_private; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b82c7c327..60fc2f658 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1444,6 +1444,8 @@ glamor_composite_with_shader(CARD8 op, #endif DEBUGF("finish rendering.\n"); dispatch->glUseProgram(0); + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; if (saved_source_format) source->format = saved_source_format; glamor_put_dispatch(glamor_priv); @@ -1665,6 +1667,7 @@ glamor_composite_clipped_region(CARD8 op, prect[i].y_dst = box[i].y1; prect[i].width = box[i].x2 - box[i].x1; prect[i].height = box[i].y2 - box[i].y1; + DEBUGF("dest %d %d \n", prect[i].x_dst, prect[i].y_dst); } ok = glamor_composite_with_shader(op, temp_src, temp_mask, dest, temp_src_priv, temp_mask_priv, @@ -1722,7 +1725,6 @@ _glamor_composite(CARD8 op, DrawablePtr saved_source_drawable; DrawablePtr saved_mask_drawable; int force_clip = 0; - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (source->pDrawable) { diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 7809e8bf8..60486cfc0 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -185,6 +185,9 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile, dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); glamor_put_dispatch(glamor_priv); + + glamor_priv->state = RENDER_STATE; + glamor_priv->render_idle_cnt = 0; } Bool From 88c317fb1e6a9056acab4a76c0ee0bf283e001ce Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 4 Jul 2012 17:59:25 +0800 Subject: [PATCH 416/462] glamor_glyphs: Don't merge extents for different lists. If we merge all lists's extent together, than we may have some fail overlap checking. Here is a simple: A E B F C D The first list has vertical "ABCD". And the second list has two char "EF". When detecting E, it can successfully find it doesn't overlap with previous glyphs. But after that, the original code will merge the previous extent with E's extent, then the extent will cover "F", so when detecting F, it will be treated as overlapped. We can simply solve this issue by not merge extent from different list. We can union different list's extent to a global region. And then do the intersect checkint between that region and current glyph extent, then we can avoid that fail checking. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 110 ++++++++++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 39 deletions(-) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index f63feac77..bab2c2465 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -616,7 +616,6 @@ glyph_new_fixed_list(struct glamor_glyph_list *fixed_list, int *head_y, int *fixed_cnt, int type, - GlyphListPtr prev_list, BoxPtr prev_extents ) { @@ -708,26 +707,39 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, int x1, x2, y1, y2; int n; int x, y; - BoxRec extents, prev_extents; - Bool first = TRUE; + BoxPtr extents; + BoxRec prev_extents; + Bool first = TRUE, first_list = TRUE; + Bool need_free_list_region = FALSE; Bool need_free_fixed_list = FALSE; struct glamor_glyph *priv; Bool in_non_intersected_list = -1; - GlyphListPtr head_list, prev_list, saved_list; + GlyphListPtr head_list, saved_list; int head_x, head_y, head_pos; int fixed_cnt = 0; GlyphPtr *head_glyphs; GlyphListPtr cur_list = list; + RegionRec list_region; + RegionRec current_region; + BoxRec current_box; + + if (nlist > 1) { + pixman_region_init(&list_region); + need_free_list_region = TRUE; + } + + pixman_region_init(¤t_region); + + extents = pixman_region_extents(¤t_region); saved_list = list; x = 0; y = 0; - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = 0; - extents.y2 = 0; - prev_extents = extents; - prev_list = list; + extents->x1 = 0; + extents->y1 = 0; + extents->x2 = 0; + extents->y2 = 0; + head_list = list; DEBUGF("has %d lists.\n", nlist); while (nlist--) { @@ -742,6 +754,18 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, left_to_right = TRUE; cur_list = list++; + if (unlikely(!first_list)) { + pixman_region_init_with_extents(¤t_region, extents); + pixman_region_union(&list_region, &list_region, ¤t_region); + first = TRUE; + } else { + head_list = cur_list; + head_pos = cur_list->len - n; + head_x = x; + head_y = y; + head_glyphs = glyphs; + } + DEBUGF("current list %p has %d glyphs\n", cur_list, n); while (n--) { GlyphPtr glyph = *glyphs++; @@ -777,17 +801,14 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, y2 = MAXSHORT; if (first) { - extents.x1 = x1; - extents.y1 = y1; - extents.x2 = x2; - extents.y2 = y2; + extents->x1 = x1; + extents->y1 = y1; + extents->x2 = x2; + extents->y2 = y2; + + prev_extents = *extents; first = FALSE; - head_list = cur_list; - head_pos = cur_list->len - n - 1; - head_x = x; - head_y = y; - head_glyphs = glyphs - 1; if (check_fake_overlap && priv && priv->has_edge_map && glyph->info.yOff == 0) { left_box.x1 = x1; @@ -802,10 +823,20 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, has_right_edge_box = TRUE; } } else { + if (unlikely(!first_list)) { + current_box.x1 = x1; + current_box.y1 = y1; + current_box.x2 = x2; + current_box.y2 = y2; + if (pixman_region_contains_rectangle(&list_region, ¤t_box) != PIXMAN_REGION_OUT) { + need_free_fixed_list = TRUE; + goto done; + } + } - if (x1 < extents.x2 && x2 > extents.x1 - && y1 < extents.y2 - && y2 > extents.y1) { + if (x1 < extents->x2 && x2 > extents->x1 + && y1 < extents->y2 + && y2 > extents->y1) { if (check_fake_overlap && (has_left_edge_box || has_right_edge_box) && priv->has_edge_map && glyph->info.yOff == 0) { @@ -814,7 +845,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, left_dx = has_left_edge_box ? 1 : 0; right_dx = has_right_edge_box ? 1 : 0; - if (x1 + 1 < extents.x2 - right_dx && x2 - 1 > extents.x1 + left_dx) + if (x1 + 1 < extents->x2 - right_dx && x2 - 1 > extents->x1 + left_dx) goto real_intersected; if (left_to_right && has_right_edge_box) { @@ -851,7 +882,7 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, goto real_intersected; } } else { - if (x1 < extents.x2 && x1 + 2 > extents.x1) + if (x1 < extents->x2 && x1 + 2 > extents->x1) goto real_intersected; } goto non_intersected; @@ -874,7 +905,6 @@ real_intersected: &head_x, &head_y, &fixed_cnt, NON_INTERSECTED, - prev_list, &prev_extents )){ need_free_fixed_list = TRUE; @@ -904,7 +934,6 @@ non_intersected: &head_x, &head_y, &fixed_cnt, INTERSECTED, - prev_list, &prev_extents )) { need_free_fixed_list = TRUE; @@ -913,12 +942,12 @@ non_intersected: } in_non_intersected_list = 1; } - prev_extents = extents; + prev_extents = *extents; } if (check_fake_overlap && priv && priv->has_edge_map && glyph->info.yOff == 0) { - if (!has_left_edge_box || x1 < extents.x1) { + if (!has_left_edge_box || x1 < extents->x1) { left_box.x1 = x1; left_box.x2 = x1 + 1; left_box.y1 = y1; @@ -926,7 +955,7 @@ non_intersected: left_priv = priv; } - if (!has_right_edge_box || x2 > extents.x2) { + if (!has_right_edge_box || x2 > extents->x2) { right_box.x1 = x2 - 2; right_box.x2 = x2 - 1; right_box.y1 = y1; @@ -935,20 +964,20 @@ non_intersected: } } - if (x1 < extents.x1) - extents.x1 = x1; - if (x2 > extents.x2) - extents.x2 = x2; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; - if (y1 < extents.y1) - extents.y1 = y1; - if (y2 > extents.y2) - extents.y2 = y2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; x += glyph->info.xOff; y += glyph->info.yOff; - prev_list = cur_list; } + first_list = FALSE; } if (in_non_intersected_list == 0 && fixed_cnt == 0) { @@ -973,7 +1002,6 @@ non_intersected: &head_x, &head_y, &fixed_cnt, (!in_non_intersected_list) | 0x80, - prev_list, &prev_extents )) { need_free_fixed_list = TRUE; @@ -982,6 +1010,10 @@ non_intersected: } done: + if (need_free_list_region) + pixman_region_fini(&list_region); + pixman_region_fini(¤t_region); + if (need_free_fixed_list && fixed_cnt >= 0) { while(fixed_cnt--) { free(fixed_list[fixed_cnt].list); From 551ca11c77d0524ceb37eb26caf0c25e4d7d806f Mon Sep 17 00:00:00 2001 From: Michel D=C3=A4nzer Date: Wed, 11 Jul 2012 15:01:15 +0800 Subject: [PATCH 417/462] Fix translation of clip region for composite fallback. Fixes incorrectly clipped rendering. E.g. the cursor in Evolution composer windows became invisible. Signed-off-by: Michel Daenzer Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 60fc2f658..d986e9a96 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -1869,13 +1869,13 @@ fail: width, height, access); \ if (sub_ ##p ##_pixmap != NULL) { \ saved_ ##p ##_drawable = p->pDrawable; \ - p->pDrawable = &sub_ ##p ##_pixmap->drawable; \ saved_ ##p ##_x = x_ ##p; \ saved_ ##p ##_y = y_ ##p; \ if (p->pCompositeClip) \ pixman_region_translate (p->pCompositeClip, \ -p->pDrawable->x - x_ ##p, \ -p->pDrawable->y - y_ ##p); \ + p->pDrawable = &sub_ ##p ##_pixmap->drawable; \ x_ ##p = 0; \ y_ ##p = 0; \ } } while(0) @@ -1910,11 +1910,11 @@ full_fallback: if (sub_ ##p ##_pixmap != NULL) { \ x_ ##p = saved_ ##p ##_x; \ y_ ##p = saved_ ##p ##_y; \ + p->pDrawable = saved_ ##p ##_drawable; \ if (p->pCompositeClip) \ pixman_region_translate (p->pCompositeClip, \ p->pDrawable->x + x_ ##p, \ p->pDrawable->y + y_ ##p); \ - p->pDrawable = saved_ ##p ##_drawable; \ glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap, \ x_ ##p + p ##_x_off + p->pDrawable->x, \ y_ ##p + p ##_y_off + p->pDrawable->y, \ From 006fe0e66df4b214ca5c50241b3cca22d31161df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 12 Jul 2012 18:57:06 +0800 Subject: [PATCH 418/462] Stream vertex data to VBOs. Reviewed-by: Chris Wilson Signed-off-by: Zhigang Gong --- glamor/glamor_render.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index d986e9a96..b5046861d 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -725,34 +725,34 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; int vert_size; - Bool need_new_buffer = FALSE; - glamor_priv->vbo_offset = 0; glamor_priv->render_nr_verts = 0; - vert_size = n_verts * sizeof(float) * 2; - - if (glamor_priv->vbo_size < vert_size) { - glamor_priv->vbo_size = vert_size; - need_new_buffer = TRUE; - } - 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); + vert_size = n_verts * glamor_priv->vb_stride; + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - if (need_new_buffer) + if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) { + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * + glamor_priv->vb_stride; + glamor_priv->vbo_offset = 0; dispatch->glBufferData(GL_ARRAY_BUFFER, - vert_size, - NULL, GL_DYNAMIC_DRAW); - glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER, 0, - vert_size, - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + glamor_priv->vbo_size, + NULL, GL_STREAM_DRAW); + } + + glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + vert_size, + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); assert(glamor_priv->vb != NULL); + glamor_priv->vb -= glamor_priv->vbo_offset; } dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); From 4c27ca4700e4ba4ae19d77377a7776eb32f74647 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 13 Jul 2012 09:20:02 +0800 Subject: [PATCH 419/462] gles2: Fixed the compilation problem and some bugs. Previous patch doesn't set the offset to zero for GLESv2 path. Now fix it. This patch also fix a minor problem in pixmap uploading preparation. If the revert is not REVERT_NORMAL, then we don't need to prepare a fbo for it. As current mesa i965 gles2 driver doesn't support to set a A8 texture as a fbo target, we must fix this problem. As some A1/A8 picture need to be uploaded, this is the only place a A8 texture may be attached to a fbo. This patch also enable the shader gradient for GLESv2. The reason we disable it before is that some glsl linker doesn't support link different objects which have cross reference. Now we don't have that problem. Signed-off-by: Zhigang Gong --- glamor/glamor_glext.h | 3 +++ glamor/glamor_pixmap.c | 2 +- glamor/glamor_priv.h | 2 -- glamor/glamor_render.c | 4 +++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_glext.h b/glamor/glamor_glext.h index d60c69690..1f7206b99 100644 --- a/glamor/glamor_glext.h +++ b/glamor/glamor_glext.h @@ -57,5 +57,8 @@ #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 #define GL_PACK_INVERT_MESA 0x8758 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 #endif diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 10066a6b5..f3a2a87ab 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -612,7 +612,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int return 0; if (!(no_alpha - || (revert != REVERT_NONE) + || (revert == REVERT_NORMAL) || (swap_rb != SWAP_NONE_UPLOADING) || !glamor_priv->yInverted)) { /* We don't need a fbo, a simple texture uploading should work. */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0703c076d..3b64c31e7 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -1014,10 +1014,8 @@ glamor_composite_rectangles(CARD8 op, * this will increase performance obviously. */ #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD -#ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER //#define GLAMOR_TRAPEZOID_SHADER -#endif #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #define WALKAROUND_LARGE_TEXTURE_MAP #if 0 diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index b5046861d..6dacd4466 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -753,7 +753,9 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts) GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); assert(glamor_priv->vb != NULL); glamor_priv->vb -= glamor_priv->vbo_offset; - } + } else + glamor_priv->vbo_offset = 0; + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, From bc1b412b3b0bb716702ec89ae512f2b5ec62c17a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 16 Jul 2012 11:25:09 +0800 Subject: [PATCH 420/462] Synch with xorg 1.13 change. As xorg 1.13 change the scrn interaces and remove those global arrays. Some API change cause we can't build. Now fix it. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 4 ++-- glamor/glamor.h | 9 ++++++--- glamor/glamor_egl.c | 16 +++++++++++----- glamor/glamor_priv.h | 1 + glamor/glamor_utils.h | 3 +++ 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 8b7dc930d..d51811e5d 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -491,7 +491,7 @@ glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) } Bool -glamor_close_screen(int idx, ScreenPtr screen) +glamor_close_screen(CLOSE_SCREEN_ARGS_DECL) { glamor_screen_private *glamor_priv; PixmapPtr screen_pixmap; @@ -533,7 +533,7 @@ glamor_close_screen(int idx, ScreenPtr screen) glamor_release_screen_priv(screen); - return screen->CloseScreen(idx, screen); + return screen->CloseScreen(CLOSE_SCREEN_ARGS); } diff --git a/glamor/glamor.h b/glamor/glamor.h index fe3e4f849..bafd543b5 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -30,9 +30,8 @@ #define GLAMOR_H #include -#ifdef GLAMOR_FOR_XORG +#include #include -#endif #include #include #include @@ -117,7 +116,11 @@ extern _X_EXPORT void glamor_fini(ScreenPtr screen); * screen pixmap which must be a glamor pixmap and requires * the internal data structure still exist at that time. * Otherwise, the glamor internal structure will not be freed.*/ -extern _X_EXPORT Bool glamor_close_screen(int idx, ScreenPtr screen); +#ifndef XF86_SCRN_INTERFACE +extern _X_EXPORT Bool glamor_close_screen(int scrnIndex, ScreenPtr screen); +#else +extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen); +#endif /* Let glamor to know the screen's fbo. The low level diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 07acf1a37..da9283b11 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -59,6 +59,7 @@ #include #include "glamor.h" +#include "compat-api.h" #include "glamor_gl_dispatch.h" #ifdef GLX_USE_SHARED_DISPATCH #include "glapi.h" @@ -365,7 +366,7 @@ glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) } static Bool -glamor_egl_close_screen(int idx, ScreenPtr screen) +glamor_egl_close_screen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr scrn; struct glamor_egl_screen_private *glamor_egl; @@ -391,7 +392,7 @@ glamor_egl_close_screen(int idx, ScreenPtr screen) screen->CloseScreen = glamor_egl->saved_close_screen; - return screen->CloseScreen(idx, screen); + return screen->CloseScreen(CLOSE_SCREEN_ARGS); } static Bool @@ -430,10 +431,15 @@ glamor_egl_screen_init(ScreenPtr screen) } static void -glamor_egl_free_screen(int scrnIndex, int flags) +glamor_egl_free_screen(FREE_SCREEN_ARGS_DECL) { - ScrnInfoPtr scrn = xf86Screens[scrnIndex]; + ScrnInfoPtr scrn; struct glamor_egl_screen_private *glamor_egl; +#ifndef XF86_SCRN_INTERFACE + scrn = xf86Screens[arg]; +#else + scrn = arg; +#endif glamor_egl = glamor_egl_get_screen_private(scrn); if (glamor_egl != NULL) { @@ -447,7 +453,7 @@ glamor_egl_free_screen(int scrnIndex, int flags) #endif scrn->FreeScreen = glamor_egl->saved_free_screen; free(glamor_egl); - scrn->FreeScreen(scrnIndex, flags); + scrn->FreeScreen(FREE_SCREEN_ARGS); } } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 3b64c31e7..11d09c454 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -38,6 +38,7 @@ #define NDEBUG #endif #include "glamor.h" +#include "compat-api.h" #define GL_GLEXT_PROTOTYPES diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index a2829855f..eb2e202f3 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -798,7 +798,10 @@ region_is_empty(pixman_region16_t *region) return region->data && region->data->numRects == 0; } +#ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) From 9dff3378e5c39b346985924f9ab6291069cc7b6e Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 16 Jul 2012 17:27:22 +0800 Subject: [PATCH 421/462] Added the missed header file for xorg 1.13 compat. Signed-off-by: Zhigang Gong --- glamor/compat-api.h | 107 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 glamor/compat-api.h diff --git a/glamor/compat-api.h b/glamor/compat-api.h new file mode 100644 index 000000000..1608478f8 --- /dev/null +++ b/glamor/compat-api.h @@ -0,0 +1,107 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Dave Airlie + */ + +/* this file provides API compat between server post 1.13 and pre it, + it should be reused inside as many drivers as possible */ +#ifndef COMPAT_API_H +#define COMPAT_API_H + +#ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR +#define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum] +#define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p +#endif + +#ifndef XF86_HAS_SCRN_CONV +#define xf86ScreenToScrn(s) xf86Screens[(s)->myNum] +#define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex] +#endif + +#ifndef XF86_SCRN_INTERFACE + +#define SCRN_ARG_TYPE int +#define SCRN_INFO_PTR(arg1) ScrnInfoPtr scrn = xf86Screens[(arg1)] + +#define SCREEN_ARG_TYPE int +#define SCREEN_PTR(arg1) ScreenPtr screen = screenInfo.screens[(arg1)] + +#define SCREEN_INIT_ARGS_DECL int scrnIndex, ScreenPtr screen, int argc, char **argv + +#define BLOCKHANDLER_ARGS_DECL int arg, pointer blockData, pointer timeout, pointer read_mask +#define BLOCKHANDLER_ARGS arg, blockData, timeout, read_mask + +#define WAKEUPHANDLER_ARGS_DECL int arg, pointer wakeupData, unsigned long result, pointer read_mask +#define WAKEUPHANDLER_ARGS arg, wakeupData, result, read_mask + +#define CLOSE_SCREEN_ARGS_DECL int scrnIndex, ScreenPtr screen +#define CLOSE_SCREEN_ARGS scrnIndex, screen + +#define ADJUST_FRAME_ARGS_DECL int arg, int x, int y, int flags +#define ADJUST_FRAME_ARGS(arg, x, y) (arg)->scrnIndex, x, y, 0 + +#define SWITCH_MODE_ARGS_DECL int arg, DisplayModePtr mode, int flags +#define SWITCH_MODE_ARGS(arg, m) (arg)->scrnIndex, m, 0 + +#define FREE_SCREEN_ARGS_DECL int arg, int flags +#define FREE_SCREEN_ARGS arg, flags + +#define VT_FUNC_ARGS_DECL int arg, int flags +#define VT_FUNC_ARGS(flags) scrn->scrnIndex, (flags) + +#define XF86_ENABLEDISABLEFB_ARG(x) ((x)->scrnIndex) + +#else +#define SCRN_ARG_TYPE ScrnInfoPtr +#define SCRN_INFO_PTR(arg1) ScrnInfoPtr scrn = (arg1) + +#define SCREEN_ARG_TYPE ScreenPtr +#define SCREEN_PTR(arg1) ScreenPtr screen = (arg1) + +#define SCREEN_INIT_ARGS_DECL ScreenPtr screen, int argc, char **argv + +#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer timeout, pointer read_mask +#define BLOCKHANDLER_ARGS arg, timeout, read_mask + +#define WAKEUPHANDLER_ARGS_DECL ScreenPtr arg, unsigned long result, pointer read_mask +#define WAKEUPHANDLER_ARGS arg, result, read_mask + +#define CLOSE_SCREEN_ARGS_DECL ScreenPtr screen +#define CLOSE_SCREEN_ARGS screen + +#define ADJUST_FRAME_ARGS_DECL ScrnInfoPtr arg, int x, int y +#define ADJUST_FRAME_ARGS(arg, x, y) arg, x, y + +#define SWITCH_MODE_ARGS_DECL ScrnInfoPtr arg, DisplayModePtr mode +#define SWITCH_MODE_ARGS(arg, m) arg, m + +#define FREE_SCREEN_ARGS_DECL ScrnInfoPtr arg +#define FREE_SCREEN_ARGS arg + +#define VT_FUNC_ARGS_DECL ScrnInfoPtr arg +#define VT_FUNC_ARGS(flags) scrn + +#define XF86_ENABLEDISABLEFB_ARG(x) (x) + +#endif +#endif From fe024a78220a6d61c6b1df89166da953b19b633a Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 20 Jul 2012 05:52:43 +0800 Subject: [PATCH 422/462] Change the trapezoid render to use VBO. Because some uniform variables need to be set for every trapezoid rendering, we can not use vbo to render multi trapezoids one time, which have performance big loss. We now add attributes which contain the same value to bypass the uniform variable problem. The uniform value for one trapezoid will be set to the same value to all the vertex of that trapezoid as an attribute, then in FS, it is still a constant. Signed-off-by: Junyan He --- glamor/glamor_trapezoid.c | 464 ++++++++++++++++++++++++-------------- glamor/glamor_utils.h | 29 +++ 2 files changed, 325 insertions(+), 168 deletions(-) diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 5dd2792d7..d7bba667b 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -38,6 +38,10 @@ #ifdef GLAMOR_TRAPEZOID_SHADER +#define GLAMOR_VERTEX_TOP_BOTTOM (GLAMOR_VERTEX_SOURCE + 1) +#define GLAMOR_VERTEX_LEFT_PARAM (GLAMOR_VERTEX_SOURCE + 2) +#define GLAMOR_VERTEX_RIGHT_PARAM (GLAMOR_VERTEX_SOURCE + 3) + #define DEBUG_CLIP_VTX 0 #define POINT_INSIDE_CLIP_RECT(point, rect) \ @@ -112,10 +116,10 @@ point_inside_trapezoid(int point[2], xTrapezoid * trap, xFixed cut_y) ret = FALSE; if (DEBUG_CLIP_VTX) { ErrorF("Out of Trap top, point[1] = %d(0x%x)), " - "top = %d(0x%x)\n", - (unsigned int)xFixedToInt(point[1]), point[1], - (unsigned int)xFixedToInt(trap->top), - (unsigned int)trap->top); + "top = %d(0x%x)\n", + (unsigned int)xFixedToInt(point[1]), point[1], + (unsigned int)xFixedToInt(trap->top), + (unsigned int)trap->top); } return ret; @@ -556,6 +560,99 @@ _glamor_clip_trapezoid_vertex(xTrapezoid * trap, BoxPtr pbox, return TRUE; } +static void +glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch; + int stride; + int vert_size; + + glamor_priv->render_nr_verts = 0; + + /* For GLAMOR_VERTEX_POS */ + glamor_priv->vb_stride = 2 * sizeof(float); + + /* For GLAMOR_GLAMOR_VERTEX_SOURCE */ + glamor_priv->vb_stride += 2 * sizeof(float); + + /* For GLAMOR_VERTEX_TOP_BOTTOM */ + glamor_priv->vb_stride += 2 * sizeof(float); + + /* For GLAMOR_VERTEX_LEFT_PARAM */ + glamor_priv->vb_stride += 4 * sizeof(float); + + /* For GLAMOR_VERTEX_RIGHT_PARAM */ + glamor_priv->vb_stride += 4 * sizeof(float); + + vert_size = n_verts * glamor_priv->vb_stride; + + dispatch = glamor_get_dispatch(glamor_priv); + + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM); + + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) { + glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * + glamor_priv->vb_stride; + glamor_priv->vbo_offset = 0; + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_size, + NULL, GL_STREAM_DRAW); + } + + glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + vert_size, + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + + assert(glamor_priv->vb != NULL); + glamor_priv->vb -= glamor_priv->vbo_offset; + } else { + glamor_priv->vbo_offset = 0; + } + + dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); + + /* Set the vertex pointer. */ + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long)glamor_priv->vbo_offset)); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + stride = 2; + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long)glamor_priv->vbo_offset + stride * sizeof(float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + stride += 2; + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long)glamor_priv->vbo_offset + stride * sizeof(float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM); + stride += 2; + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long)glamor_priv->vbo_offset + stride * sizeof(float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM); + stride += 4; + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT, + GL_FALSE, glamor_priv->vb_stride, + (void *) ((long)glamor_priv->vbo_offset + stride * sizeof(float))); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM); + + glamor_put_dispatch(glamor_priv); +} + static Bool _glamor_trapezoids_with_shader(CARD8 op, PicturePtr src, PicturePtr dst, @@ -565,6 +662,8 @@ _glamor_trapezoids_with_shader(CARD8 op, ScreenPtr screen = dst->pDrawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); struct shader_key key; + glamor_composite_shader *shader = NULL; + struct blendinfo op_info; PictFormatShort saved_source_format = 0; PixmapPtr source_pixmap = NULL; PixmapPtr dest_pixmap = NULL; @@ -707,7 +806,7 @@ _glamor_trapezoids_with_shader(CARD8 op, goto TRAPEZOID_RESET_GL; } glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); - glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, op_info); + glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info); 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); @@ -888,13 +987,45 @@ glamor_init_trapezoid_shader(ScreenPtr screen) const char *trapezoid_vs = GLAMOR_DEFAULT_PRECISION "attribute vec4 v_position;\n" - "attribute vec4 v_texcoord;\n" + "attribute vec2 v_texcoord;\n" + /* v_top_bottom, v_left_param and v_right_param contain the + constant value for all the vertex of one rect. Using uniform + is more suitable but we need to reset the uniform variables + for every rect rendering and can not use the vbo, which causes + performance loss. So we set these attributes to same value + for every vertex of one rect and so it is also a constant in FS */ + "attribute vec2 v_top_bottom;\n" + "attribute vec4 v_left_param;\n" + "attribute vec4 v_right_param;\n" + "\n" "varying vec2 source_texture;\n" + "varying float trap_top;\n" + "varying float trap_bottom;\n" + "varying float trap_left_x;\n" + "varying float trap_left_y;\n" + "varying float trap_left_slope;\n" + "varying float trap_left_vertical_f;\n" + "varying float trap_right_x;\n" + "varying float trap_right_y;\n" + "varying float trap_right_slope;\n" + "varying float trap_right_vertical_f;\n" "\n" "void main()\n" "{\n" " gl_Position = v_position;\n" " source_texture = v_texcoord.xy;\n" + " trap_top = v_top_bottom.x;\n" + " trap_bottom = v_top_bottom.y;\n" + " \n" + " trap_left_x = v_left_param.x;\n" + " trap_left_y = v_left_param.y;\n" + " trap_left_slope = v_left_param.z;\n" + " trap_left_vertical_f = v_left_param.w;\n" + " \n" + " trap_right_x = v_right_param.x;\n" + " trap_right_y = v_right_param.y;\n" + " trap_right_slope = v_right_param.z;\n" + " trap_right_vertical_f = v_right_param.w;\n" "}\n"; /* @@ -925,18 +1056,20 @@ glamor_init_trapezoid_shader(ScreenPtr screen) const char *trapezoid_fs = GLAMOR_DEFAULT_PRECISION "varying vec2 source_texture; \n" - "uniform float x_per_pix; \n" - "uniform float y_per_pix; \n" - "uniform float trap_top; \n" - "uniform float trap_bottom; \n" - "uniform float trap_left_x; \n" - "uniform float trap_left_y; \n" - "uniform float trap_left_slope; \n" - "uniform int trap_left_vertical; \n" - "uniform float trap_right_x; \n" - "uniform float trap_right_y; \n" - "uniform float trap_right_slope; \n" - "uniform int trap_right_vertical; \n" + "varying float trap_top; \n" + "varying float trap_bottom; \n" + "varying float trap_left_x; \n" + "varying float trap_left_y; \n" + "varying float trap_left_slope; \n" + "varying float trap_left_vertical_f; \n" + "varying float trap_right_x; \n" + "varying float trap_right_y; \n" + "varying float trap_right_slope; \n" + "varying float trap_right_vertical_f; \n" + "float x_per_pix = 1.0;" + "float y_per_pix = 1.0;" + "bool trap_left_vertical = (abs(trap_left_vertical_f - 1.0) <= 0.0001);\n" + "bool trap_right_vertical = (abs(trap_right_vertical_f - 1.0) <= 0.0001);\n" "\n" "float get_alpha_val() \n" "{ \n" @@ -945,7 +1078,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen) " float x_up_cut_right; \n" " float x_bottom_cut_right; \n" " \n" - " if(trap_left_vertical == 1) { \n" + " if(trap_left_vertical == true) { \n" " x_up_cut_left = trap_left_x; \n" " x_bottom_cut_left = trap_left_x; \n" " } else { \n" @@ -957,7 +1090,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen) " / trap_left_slope; \n" " } \n" " \n" - " if(trap_right_vertical == 1) { \n" + " if(trap_right_vertical == true) { \n" " x_up_cut_right = trap_right_x; \n" " x_bottom_cut_right = trap_right_x; \n" " } else { \n" @@ -1002,12 +1135,12 @@ glamor_init_trapezoid_shader(ScreenPtr screen) " \n" " percent = (bottom - up) / y_per_pix; \n" " \n" - " if(trap_left_vertical == 1) { \n" + " if(trap_left_vertical == true) { \n" " if(trap_left_x > source_texture.x - x_per_pix/2.0 && \n" " trap_left_x < source_texture.x + x_per_pix/2.0) \n" " left = trap_left_x; \n" " } \n" - " if(trap_right_vertical == 1) { \n" + " if(trap_right_vertical == true) { \n" " if(trap_right_x > source_texture.x - x_per_pix/2.0 && \n" " trap_right_x < source_texture.x + x_per_pix/2.0) \n" " right = trap_right_x; \n" @@ -1016,10 +1149,10 @@ glamor_init_trapezoid_shader(ScreenPtr screen) " return 0.0; \n" " \n" " percent = percent * ((right - left)/x_per_pix); \n" - " if(trap_left_vertical == 1 && trap_right_vertical == 1) \n" + " if(trap_left_vertical == true && trap_right_vertical == true) \n" " return percent; \n" " \n" - " if(trap_left_vertical != 1) { \n" + " if(trap_left_vertical != true) { \n" " float area; \n" // the slope should never be 0.0 here " float up_x = trap_left_x + (up - trap_left_y)/trap_left_slope; \n" @@ -1090,7 +1223,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen) " } \n" " } \n" " \n" - " if(trap_right_vertical != 1) { \n" + " if(trap_right_vertical != true) { \n" " float area; \n" // the slope should never be 0.0 here " float up_x = trap_right_x + (up - trap_right_y)/trap_right_slope; \n" @@ -1184,9 +1317,15 @@ glamor_init_trapezoid_shader(ScreenPtr screen) dispatch->glAttachShader(glamor_priv->trapezoid_prog, fs_prog); dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, - GLAMOR_VERTEX_POS, "v_positionsition"); + GLAMOR_VERTEX_POS, "v_positionsition"); dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, - GLAMOR_VERTEX_SOURCE, "v_texcoord"); + GLAMOR_VERTEX_SOURCE, "v_texcoord"); + dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, + GLAMOR_VERTEX_TOP_BOTTOM, "v_top_bottom"); + dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, + GLAMOR_VERTEX_LEFT_PARAM, "v_left_param"); + dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog, + GLAMOR_VERTEX_RIGHT_PARAM, "v_right_param"); glamor_link_glsl_prog(dispatch, glamor_priv->trapezoid_prog); @@ -1215,28 +1354,16 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, glamor_gl_dispatch *dispatch; glamor_pixmap_private *pixmap_priv; PixmapPtr pixmap = NULL; - GLint x_per_pix_uniform_location; - GLint y_per_pix_uniform_location; - GLint trap_top_uniform_location; - GLint trap_bottom_uniform_location; - GLint trap_left_x_uniform_location; - GLint trap_left_y_uniform_location; - GLint trap_left_slope_uniform_location; - GLint trap_right_x_uniform_location; - GLint trap_right_y_uniform_location; - GLint trap_right_slope_uniform_location; - GLint trap_left_vertical_uniform_location; - GLint trap_right_vertical_uniform_location; GLint trapezoid_prog; float width, height; - xFixed width_fix, height_fix; GLfloat xscale, yscale; float left_slope, right_slope; xTrapezoid *ptrap; BoxRec one_trap_bound; - float vertices[8]; - float tex_vertices[8]; - int i; + int nrect_max; + int i, j; + float *vertices; + float params[4]; glamor_priv = glamor_get_screen_private(screen); trapezoid_prog = glamor_priv->trapezoid_prog; @@ -1245,7 +1372,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) - || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { /* should always have here. */ + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { /* should always have here. */ DEBUGF("GLAMOR_PIXMAP_PRIV_HAS_FBO check failed, fallback\n"); return FALSE; } @@ -1260,155 +1387,153 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, dispatch = glamor_get_dispatch(glamor_priv); - /* Bind all the uniform vars .*/ - x_per_pix_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "x_per_pix"); - y_per_pix_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "y_per_pix"); - trap_top_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_top"); - trap_bottom_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_bottom"); - trap_left_x_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_x"); - trap_left_y_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_y"); - trap_left_slope_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_slope"); - trap_left_vertical_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_left_vertical"); - trap_right_x_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_x"); - trap_right_y_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_y"); - trap_right_slope_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_slope"); - trap_right_vertical_uniform_location = - dispatch->glGetUniformLocation(trapezoid_prog, "trap_right_vertical"); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale)); width = (float)(bounds->x2 - bounds->x1); height = (float)(bounds->y2 - bounds->y1); - width_fix = IntToxFixed((bounds->x2 - bounds->x1)); - height_fix = IntToxFixed((bounds->y2 - bounds->y1)); dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - /* Now draw the Trapezoid mask. */ dispatch->glUseProgram(trapezoid_prog); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 0, vertices); - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, - GL_FALSE, 0, tex_vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glEnable(GL_BLEND); dispatch->glBlendFunc(GL_ONE, GL_ONE); - for (i = 0; i < ntrap; i++) { - ptrap = traps + i; + nrect_max = GLAMOR_COMPOSITE_VBO_VERT_CNT / (4 * GLAMOR_VERTEX_RIGHT_PARAM); - DEBUGF("--- The parameter of xTrapezoid is:\ntop: %d 0x%x\tbottom: %d 0x%x\n" - "left: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n" - "right: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n", - xFixedToInt(ptrap->top), ptrap->top, - xFixedToInt(ptrap->bottom), ptrap->bottom, - xFixedToInt(ptrap->left.p1.x), ptrap->left.p1.x, - xFixedToInt(ptrap->left.p1.y), ptrap->left.p1.y, - xFixedToInt(ptrap->left.p2.x), ptrap->left.p2.x, - xFixedToInt(ptrap->left.p2.y), ptrap->left.p2.y, - xFixedToInt(ptrap->right.p1.x), ptrap->right.p1.x, - xFixedToInt(ptrap->right.p1.y), ptrap->right.p1.y, - xFixedToInt(ptrap->right.p2.x), ptrap->right.p2.x, - xFixedToInt(ptrap->right.p2.y), ptrap->right.p2.y); + for (i = 0; i < ntrap;) { + int mrect; + int stride; - miTrapezoidBounds(1, ptrap, &one_trap_bound); - glamor_set_tcoords_tri_strip((pixmap_priv->base.pixmap->drawable.width), - (pixmap_priv->base.pixmap->drawable.height), - (one_trap_bound.x1), - (one_trap_bound.y1), - (one_trap_bound.x2), - (one_trap_bound.y2), - glamor_priv->yInverted, tex_vertices); + mrect = (ntrap - i) > nrect_max ? nrect_max : (ntrap - i); + glamor_setup_composite_vbo_for_trapezoid(screen, 4 * mrect); + stride = glamor_priv->vb_stride / sizeof(float); - /* Need to rebase. */ - one_trap_bound.x1 -= bounds->x1; - one_trap_bound.x2 -= bounds->x1; - one_trap_bound.y1 -= bounds->y1; - one_trap_bound.y2 -= bounds->y1; - glamor_set_normalize_vcoords_tri_strip(xscale, yscale, - one_trap_bound.x1, one_trap_bound.y1, - one_trap_bound.x2, one_trap_bound.y2, - glamor_priv->yInverted, vertices); + for (j = 0; j < mrect; j++) { + ptrap = traps + i + j; - DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," - "rightbottom: %f X %f, leftbottom : %f X %f\n", - vertices[0], vertices[1], vertices[2], vertices[3], - vertices[4], vertices[5], vertices[6], vertices[7]); - DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," - "rightbottom: %f X %f, leftbottom : %f X %f\n", - tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3], - tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]); + DEBUGF("--- The parameter of xTrapezoid is:\ntop: %d 0x%x\tbottom: %d 0x%x\n" + "left: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n" + "right: p1 (%d 0x%x, %d 0x%x)\tp2 (%d 0x%x, %d 0x%x)\n", + xFixedToInt(ptrap->top), ptrap->top, + xFixedToInt(ptrap->bottom), ptrap->bottom, + xFixedToInt(ptrap->left.p1.x), ptrap->left.p1.x, + xFixedToInt(ptrap->left.p1.y), ptrap->left.p1.y, + xFixedToInt(ptrap->left.p2.x), ptrap->left.p2.x, + xFixedToInt(ptrap->left.p2.y), ptrap->left.p2.y, + xFixedToInt(ptrap->right.p1.x), ptrap->right.p1.x, + xFixedToInt(ptrap->right.p1.y), ptrap->right.p1.y, + xFixedToInt(ptrap->right.p2.x), ptrap->right.p2.x, + xFixedToInt(ptrap->right.p2.y), ptrap->right.p2.y); - if (ptrap->left.p1.x == ptrap->left.p2.x) { - left_slope = 0.0; - dispatch->glUniform1i(trap_left_vertical_uniform_location, 1); - } else { - left_slope = ((float)(ptrap->left.p1.y - ptrap->left.p2.y)) - / ((float)(ptrap->left.p1.x - ptrap->left.p2.x)); - dispatch->glUniform1i(trap_left_vertical_uniform_location, 0); + miTrapezoidBounds(1, ptrap, &one_trap_bound); + + vertices = (float*)(glamor_priv->vb + glamor_priv->vbo_offset) + 2; + glamor_set_tcoords_ext((pixmap_priv->base.pixmap->drawable.width), + (pixmap_priv->base.pixmap->drawable.height), + (one_trap_bound.x1), + (one_trap_bound.y1), + (one_trap_bound.x2), + (one_trap_bound.y2), + glamor_priv->yInverted, vertices, stride); + DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + vertices[0], vertices[1], + vertices[1*stride], vertices[1*stride + 1], + vertices[2*stride], vertices[2*stride + 1], + vertices[3*stride], vertices[3*stride + 1]); + + /* Need to rebase. */ + one_trap_bound.x1 -= bounds->x1; + one_trap_bound.x2 -= bounds->x1; + one_trap_bound.y1 -= bounds->y1; + one_trap_bound.y2 -= bounds->y1; + + vertices -= 2; + + glamor_set_normalize_vcoords_ext(pixmap_priv, xscale, yscale, + one_trap_bound.x1, one_trap_bound.y1, + one_trap_bound.x2, one_trap_bound.y2, + glamor_priv->yInverted, vertices, stride); + DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f," + "rightbottom: %f X %f, leftbottom : %f X %f\n", + vertices[0], vertices[1], + vertices[1*stride], vertices[1*stride + 1], + vertices[2*stride], vertices[2*stride + 1], + vertices[3*stride], vertices[3*stride + 1]); + vertices += 4; + + /* Set the top and bottom. */ + params[0] = ((float)ptrap->top) / 65536; + params[1] = ((float)ptrap->bottom) / 65536; + glamor_set_const_ext(params, 2, vertices, 4, stride); + vertices += 2; + + /* Set the left params. */ + params[0] = ((float)ptrap->left.p1.x) / 65536; + params[1] = ((float)ptrap->left.p1.y) / 65536; + + if (ptrap->left.p1.x == ptrap->left.p2.x) { + left_slope = 0.0; + params[3] = 1.0; + } else { + left_slope = ((float)(ptrap->left.p1.y - ptrap->left.p2.y)) + / ((float)(ptrap->left.p1.x - ptrap->left.p2.x)); + params[3] = 0.0; + } + params[2] = left_slope; + glamor_set_const_ext(params, 4, vertices, 4, stride); + vertices += 4; + + /* Set the left params. */ + params[0] = ((float)ptrap->right.p1.x) / 65536; + params[1] = ((float)ptrap->right.p1.y) / 65536; + + if (ptrap->right.p1.x == ptrap->right.p2.x) { + right_slope = 0.0; + params[3] = 1.0; + } else { + right_slope = ((float)(ptrap->right.p1.y - ptrap->right.p2.y)) + / ((float)(ptrap->right.p1.x - ptrap->right.p2.x)); + params[3] = 0.0; + } + params[2] = right_slope; + glamor_set_const_ext(params, 4, vertices, 4, stride); + + DEBUGF("trap_top = %f, trap_bottom = %f, " + "trap_left_x = %f, trap_left_y = %f, left_slope = %f, " + "trap_right_x = %f, trap_right_y = %f, right_slope = %f\n", + ((float)ptrap->top) / 65536, ((float)ptrap->bottom) / 65536, + ((float)ptrap->left.p1.x) / 65536, ((float)ptrap->left.p1.y) / 65536, + left_slope, + ((float)ptrap->right.p1.x) / 65536, ((float)ptrap->right.p1.y) / 65536, + right_slope); + + glamor_priv->render_nr_verts += 4; + glamor_priv->vbo_offset += glamor_priv->vb_stride * 4; } - dispatch->glUniform1f(trap_left_slope_uniform_location, left_slope); - if (ptrap->right.p1.x == ptrap->right.p2.x) { - right_slope = 0.0; - dispatch->glUniform1i(trap_right_vertical_uniform_location, 1); - } else { - right_slope = ((float)(ptrap->right.p1.y - ptrap->right.p2.y)) - / ((float)(ptrap->right.p1.x - ptrap->right.p2.x)); - dispatch->glUniform1i(trap_right_vertical_uniform_location, 0); - } - dispatch->glUniform1f(trap_right_slope_uniform_location, right_slope); - - dispatch->glUniform1f(x_per_pix_uniform_location, - ((float)width_fix) / (65536 * width)); - dispatch->glUniform1f(y_per_pix_uniform_location, - ((float)height_fix) / (65536 * height)); - - dispatch->glUniform1f(trap_top_uniform_location, - ((float)ptrap->top) / 65536); - dispatch->glUniform1f(trap_bottom_uniform_location, - ((float)ptrap->bottom) / 65536); - - dispatch->glUniform1f(trap_left_x_uniform_location, - ((float)ptrap->left.p1.x) / 65536); - dispatch->glUniform1f(trap_left_y_uniform_location, - ((float)ptrap->left.p1.y) / 65536); - dispatch->glUniform1f(trap_right_x_uniform_location, - ((float)ptrap->right.p1.x) / 65536); - dispatch->glUniform1f(trap_right_y_uniform_location, - ((float)ptrap->right.p1.y) / 65536); - - DEBUGF("x_per_pix = %f, y_per_pix = %f, trap_top = %f, trap_bottom = %f, " - "trap_left_x = %f, trap_left_y = %f, left_slope = %f, " - "trap_right_x = %f, trap_right_y = %f, right_slope = %f\n", - ((float)width_fix) / (65536*width), ((float)height_fix) / (65536*height), - ((float)ptrap->top) / 65536, ((float)ptrap->bottom) / 65536, - ((float)ptrap->left.p1.x) / 65536, ((float)ptrap->left.p1.y) / 65536, - left_slope, - ((float)ptrap->right.p1.x) / 65536, ((float)ptrap->right.p1.y) / 65536, - right_slope); + i += mrect; /* Now rendering. */ - dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (!glamor_priv->render_nr_verts) + continue; + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); + else { + dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + dispatch->glBufferData(GL_ARRAY_BUFFER, + glamor_priv->vbo_offset, + glamor_priv->vb, GL_DYNAMIC_DRAW); + } + + dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); } dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -1417,6 +1542,9 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, dispatch->glDisable(GL_BLEND); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM); dispatch->glUseProgram(0); glamor_put_dispatch(glamor_priv); return TRUE; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index eb2e202f3..6eef722ba 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -629,6 +629,25 @@ (vertices)[7] = (vertices)[5]; \ } while(0) +#define glamor_set_tcoords_ext(width, height, x1, y1, x2, y2, \ + yInverted, vertices, stride) \ + do { \ + (vertices)[0] = (x1); \ + (vertices)[1*stride] = (x2); \ + (vertices)[2*stride] = (vertices)[1*stride]; \ + (vertices)[3*stride] = (vertices)[0]; \ + if (likely(yInverted)) { \ + (vertices)[1] = (y1); \ + (vertices)[2*stride + 1] = (y2); \ + } \ + else { \ + (vertices)[1] = height - (y2); \ + (vertices)[2*stride + 1] = height - (y1); \ + } \ + (vertices)[1*stride + 1] = (vertices)[1]; \ + (vertices)[3*stride + 1] = (vertices)[2*stride + 1]; \ + } while(0) + #define glamor_set_normalize_one_vcoord(xscale, yscale, x, y, \ yInverted, vertices) \ do { \ @@ -713,6 +732,16 @@ yInverted, vertices, 2); \ } while(0) +#define glamor_set_const_ext(params, nparam, vertices, nverts, stride) \ + do { \ + int i = 0, j = 0; \ + for(; i < nverts; i++) { \ + for(j = 0; j < nparam; j++) { \ + vertices[stride*i + j] = params[j]; \ + } \ + } \ + } while(0) + #define glamor_set_normalize_vcoords_tri_strip(xscale, yscale, \ x1, y1, x2, y2, \ yInverted, vertices) \ From 9f78e22fa62d8f1a08d6a0688e2eafba35206a3b Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 20 Jul 2012 05:52:50 +0800 Subject: [PATCH 423/462] Just use the shader to generate trapezoid if PolyMode == Imprecise The precise mode of trapezoid rendering need to sample the trapezoid on the centre points of an (2*n+1)x(2*n-1) subpixel grid. It is computationally expensive in shader, and we use inside area ratio to replace it. The result has some difference, and we just use it if the polymode == Imprecise. Signed-off-by: Junyan He --- glamor/glamor_trapezoid.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index d7bba667b..5c02a8ce0 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -1664,15 +1664,20 @@ _glamor_trapezoids(CARD8 op, if(ret) return TRUE; } else { - picture = glamor_create_mask_picture(screen, dst, mask_format, - width, height, 1); - if (!picture) - return TRUE; + /* The precise mode is that we sample the trapezoid on the centre points of + an (2*n+1)x(2*n-1) subpixel grid. It is computationally expensive in shader + and we use inside area ratio to replace it if the polymode == Imprecise. */ + if(dst->polyMode == PolyModeImprecise) { + picture = glamor_create_mask_picture(screen, dst, mask_format, + width, height, 1); + if (!picture) + return TRUE; - ret = _glamor_generate_trapezoid_with_shader(screen, picture, traps, ntrap, &bounds); + ret = _glamor_generate_trapezoid_with_shader(screen, picture, traps, ntrap, &bounds); - if (!ret) - FreePicture(picture, 0); + if (!ret) + FreePicture(picture, 0); + } } #endif From 5512c14e346a988f6eb8cdf9385a868ef705450c Mon Sep 17 00:00:00 2001 From: Junyan He Date: Fri, 20 Jul 2012 05:52:57 +0800 Subject: [PATCH 424/462] Fix the problem of VBO leak. In some cases we allocate the VBO but have no vertex to emit, which cause the VBO fail to be released. Fix it. Signed-off-by: Junyan He --- glamor/glamor_render.c | 6 +++--- glamor/glamor_trapezoid.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 6dacd4466..9b80295e5 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -826,9 +826,6 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; - if (!glamor_priv->render_nr_verts) - return; - dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); @@ -840,6 +837,9 @@ glamor_flush_composite_rects(ScreenPtr screen) glamor_priv->vb, GL_DYNAMIC_DRAW); } + if (!glamor_priv->render_nr_verts) + return; + dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, GL_UNSIGNED_SHORT, NULL); glamor_put_dispatch(glamor_priv); diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 5c02a8ce0..fd63062f6 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -199,9 +199,6 @@ glamor_flush_composite_triangles(ScreenPtr screen) glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; - if (!glamor_priv->render_nr_verts) - return; - dispatch = glamor_get_dispatch(glamor_priv); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) dispatch->glUnmapBuffer(GL_ARRAY_BUFFER); @@ -213,6 +210,9 @@ glamor_flush_composite_triangles(ScreenPtr screen) glamor_priv->vb, GL_DYNAMIC_DRAW); } + if (!glamor_priv->render_nr_verts) + return; + dispatch->glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts); glamor_put_dispatch(glamor_priv); } From e7af7cb76dade31b9e40cede7ac21d32bc95831c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 1 Aug 2012 18:27:29 +0800 Subject: [PATCH 425/462] glamor_trapezoid: workaround a glsl like problem. It seems that the following statement cann't run as expected on SNB. bool trap_left_vertical = (abs(trap_left_vertical_f - 1.0) <= 0.0001); Have to rewrite it to another style to let the vertical edge trapezoid to be rendered correctly. Reviewed-by: Junyan He Signed-off-by: Zhigang Gong --- glamor/glamor_trapezoid.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index fd63062f6..7813d825d 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -1068,8 +1068,6 @@ glamor_init_trapezoid_shader(ScreenPtr screen) "varying float trap_right_vertical_f; \n" "float x_per_pix = 1.0;" "float y_per_pix = 1.0;" - "bool trap_left_vertical = (abs(trap_left_vertical_f - 1.0) <= 0.0001);\n" - "bool trap_right_vertical = (abs(trap_right_vertical_f - 1.0) <= 0.0001);\n" "\n" "float get_alpha_val() \n" "{ \n" @@ -1077,6 +1075,16 @@ glamor_init_trapezoid_shader(ScreenPtr screen) " float x_bottom_cut_left; \n" " float x_up_cut_right; \n" " float x_bottom_cut_right; \n" + " bool trap_left_vertical;\n" + " bool trap_right_vertical;\n" + " if (abs(trap_left_vertical_f - 1.0) <= 0.0001)\n" + " trap_left_vertical = true;\n" + " else\n" + " trap_left_vertical = false;\n" + " if (abs(trap_right_vertical_f - 1.0) <= 0.0001)\n" + " trap_right_vertical = true;\n" + " else\n" + " trap_right_vertical = false;\n" " \n" " if(trap_left_vertical == true) { \n" " x_up_cut_left = trap_left_x; \n" From f62f4d53ef91ba05cc9456b1468cd1b24252454f Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 2 Aug 2012 18:07:07 +0800 Subject: [PATCH 426/462] glamor_glyphs: When dst arg point to a NULL buffer, dont't flush. This is a corner case, when we render glyphs via mask cache, and when we need to upload new glyphs cache, we need to flush both the mask and dest buffer. But we the dest arg may point to a NULL buffer at that time, we need to check it firstly. If the dest buffer is NULL. Then we don't need to flush both the dest and mask buffer. This commit fix a potential crash. Signed-off-by: Zhigang Gong --- glamor/glamor_glyphs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index bab2c2465..f5499049a 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -1193,6 +1193,9 @@ glamor_glyphs_flush_mask(struct glyphs_flush_mask_arg *arg) static void glamor_glyphs_flush_dst(struct glyphs_flush_dst_arg * arg) { + if (!arg->buffer) + return; + if (mask_buffer.count > 0) { glamor_glyphs_flush_mask(&mask_arg); } From c3096c5a568c9c7b5f8a68ca882d866b8fb8e3ad Mon Sep 17 00:00:00 2001 From: Junyan He Date: Tue, 7 Aug 2012 05:01:59 +0800 Subject: [PATCH 427/462] Fallback to pixman when trapezoid mask is big. The trapezoid generating speed of the shader is relatively slower when the trapezoid area is big. We fallback when the trapezoid's width and height is bigger enough. The big traps number will also slow down the render because of the VBO size. We fallback if ntrap > 256 Signed-off-by: Junyan He Reviewed-By: Zhigang Gong --- glamor/glamor_priv.h | 2 +- glamor/glamor_trapezoid.c | 104 +++++++++++++++++++++++++++----------- 2 files changed, 75 insertions(+), 31 deletions(-) diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 11d09c454..1830b56ee 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -1016,7 +1016,7 @@ glamor_composite_rectangles(CARD8 op, #define GLAMOR_PIXMAP_DYNAMIC_UPLOAD #define GLAMOR_GRADIENT_SHADER -//#define GLAMOR_TRAPEZOID_SHADER +#define GLAMOR_TRAPEZOID_SHADER #define GLAMOR_TEXTURED_LARGE_PIXMAP 1 #define WALKAROUND_LARGE_TEXTURE_MAP #if 0 diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 7813d825d..7bb75f59b 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -36,6 +36,28 @@ #include "mipict.h" #include "fbpict.h" +static xFixed +_glamor_linefixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +static xFixed +_glamor_linefixedY (xLineFixed *l, xFixed x, Bool ceil) +{ + xFixed dy = l->p2.y - l->p1.y; + xFixed_32_32 ey = (xFixed_32_32) (x - l->p1.x) * dy; + xFixed dx = l->p2.x - l->p1.x; + if (ceil) + ey += (dx - 1); + return l->p1.y + (xFixed) (ey / dx); +} + #ifdef GLAMOR_TRAPEZOID_SHADER #define GLAMOR_VERTEX_TOP_BOTTOM (GLAMOR_VERTEX_SOURCE + 1) @@ -72,28 +94,6 @@ _glamor_lines_crossfixedY (xLineFixed *l, xLineFixed *r) return 0xFFFFFFFF; } -static xFixed -_glamor_linefixedX (xLineFixed *l, xFixed y, Bool ceil) -{ - xFixed dx = l->p2.x - l->p1.x; - xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; - xFixed dy = l->p2.y - l->p1.y; - if (ceil) - ex += (dy - 1); - return l->p1.x + (xFixed) (ex / dy); -} - -static xFixed -_glamor_linefixedY (xLineFixed *l, xFixed x, Bool ceil) -{ - xFixed dy = l->p2.y - l->p1.y; - xFixed_32_32 ey = (xFixed_32_32) (x - l->p1.x) * dy; - xFixed dx = l->p2.x - l->p1.x; - if (ceil) - ey += (dx - 1); - return l->p1.y + (xFixed) (ey / dx); -} - static Bool point_inside_trapezoid(int point[2], xTrapezoid * trap, xFixed cut_y) { @@ -1601,6 +1601,45 @@ glamor_create_mask_picture(ScreenPtr screen, return picture; } +static int +_glamor_trapezoid_bounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + int has_large_trapezoid = 0; + + for (; ntrap; ntrap--, traps++) { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (_glamor_linefixedX (&traps->left, traps->top, FALSE), + _glamor_linefixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (_glamor_linefixedX (&traps->right, traps->top, TRUE), + _glamor_linefixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + + if (!has_large_trapezoid && (x2 - x1) > 256 && (y2 - y1) > 32) + has_large_trapezoid = 1; + } + + return has_large_trapezoid; +} + /** * glamor_trapezoids will first try to create a trapezoid mask using shader, * if failed, miTrapezoids will generate trapezoid mask accumulating in @@ -1621,6 +1660,7 @@ _glamor_trapezoids(CARD8 op, PixmapPtr pixmap; pixman_image_t *image = NULL; int ret = 0; + int has_large_trapezoid; /* 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. @@ -1638,10 +1678,10 @@ _glamor_trapezoids(CARD8 op, return TRUE; } - miTrapezoidBounds(ntrap, traps, &bounds); + has_large_trapezoid = _glamor_trapezoid_bounds(ntrap, traps, &bounds); DEBUGF("The bounds for all traps is: bounds.x1 = %d, bounds.x2 = %d, " - "bounds.y1 = %d, bounds.y2 = %d\n", bounds.x1, bounds.x2, - bounds.y1, bounds.y2); + "bounds.y1 = %d, bounds.y2 = %d, ---- ntrap = %d\n", bounds.x1, + bounds.x2, bounds.y1, bounds.y2, ntrap); if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) return TRUE; @@ -1666,16 +1706,20 @@ _glamor_trapezoids(CARD8 op, When the depth is not 1, AA is needed and we use a shader to generate a temp mask pixmap. */ - if(mask_format->depth == 1) { + if (mask_format->depth == 1) { ret = _glamor_trapezoids_with_shader(op, src, dst, mask_format, x_src, y_src, ntrap, traps); if(ret) return TRUE; } else { - /* The precise mode is that we sample the trapezoid on the centre points of - an (2*n+1)x(2*n-1) subpixel grid. It is computationally expensive in shader - and we use inside area ratio to replace it if the polymode == Imprecise. */ - if(dst->polyMode == PolyModeImprecise) { + if (has_large_trapezoid || ntrap > 256) { + /* The shader speed is relative slower than pixman when generating big chunk + trapezoid mask. We fallback to pixman to improve the performance. */ + ; + } else if (dst->polyMode == PolyModeImprecise) { + /* The precise mode is that we sample the trapezoid on the centre points of + an (2*n+1)x(2*n-1) subpixel grid. It is computationally expensive in shader + and we use inside area ratio to replace it if the polymode == Imprecise. */ picture = glamor_create_mask_picture(screen, dst, mask_format, width, height, 1); if (!picture) From 59653fa08a67a0694b3408407f5f92af99470739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 7 Aug 2012 18:13:32 +0200 Subject: [PATCH 428/462] Print space between name of missing EGL extension and 'required'. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michel Dänzer Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index da9283b11..596470cd7 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -508,7 +508,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) #define GLAMOR_CHECK_EGL_EXTENSION(EXT) \ if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT)) { \ - ErrorF("EGL_" #EXT "required.\n"); \ + ErrorF("EGL_" #EXT " required.\n"); \ return FALSE; \ } From 7eb434918bd7d58162c53fac9316aceda136cb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 7 Aug 2012 18:16:58 +0200 Subject: [PATCH 429/462] Prefer KHR_surfaceless_context EGL extension over KHR_surfaceless_opengl/gles2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current Mesa Git only advertises the former instead of the latter. Signed-off-by: Michel Dänzer Signed-off-by: Zhigang Gong --- glamor/glamor_egl.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 596470cd7..a9a92a7f2 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -397,7 +397,7 @@ glamor_egl_close_screen(CLOSE_SCREEN_ARGS_DECL) static Bool glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, - char *extension) + const char *extension) { const char *egl_extensions; char *pext; @@ -512,12 +512,19 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) return FALSE; \ } +#define GLAMOR_CHECK_EGL_EXTENSIONS(EXT1, EXT2) \ + if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT1) && \ + !glamor_egl_has_extension(glamor_egl, "EGL_" #EXT2)) { \ + ErrorF("EGL_" #EXT1 " or EGL_" #EXT2 " required.\n"); \ + return FALSE; \ + } + GLAMOR_CHECK_EGL_EXTENSION(MESA_drm_image); GLAMOR_CHECK_EGL_EXTENSION(KHR_gl_renderbuffer_image); #ifdef GLAMOR_GLES2 - GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_gles2); + GLAMOR_CHECK_EGL_EXTENSIONS(KHR_surfaceless_context, KHR_surfaceless_gles2); #else - GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_opengl); + GLAMOR_CHECK_EGL_EXTENSIONS(KHR_surfaceless_context, KHR_surfaceless_opengl); #endif glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) From 50614451adafc816ae5ffbe9c2a97a58f493b927 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 8 Aug 2012 20:08:12 +0800 Subject: [PATCH 430/462] glamor_largepixmap: Fixed a bug in repeat clipping. If the repeat direction only has one block, then we need to set the dx/dy to cover all the extent. This commit also silence some compilation warnings. Signed-off-by: Zhigang Gong --- glamor/glamor_largepixmap.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c index f07095a92..91ee8f2df 100644 --- a/glamor/glamor_largepixmap.c +++ b/glamor/glamor_largepixmap.c @@ -35,7 +35,6 @@ __glamor_compute_clipped_regions(int block_w, int loop_end_block_x, loop_end_block_y; int loop_block_stride; int i, j, delta_i, delta_j; - int width, height; RegionRec temp_region; RegionPtr current_region; int block_idx; @@ -60,8 +59,6 @@ __glamor_compute_clipped_regions(int block_w, return NULL; } - width = end_x - start_x; - height = end_y - start_y; start_block_x = (start_x - x)/ block_w; start_block_y = (start_y - y)/ block_h; end_block_x = (end_x - x)/ block_w; @@ -327,7 +324,6 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, glamor_pixmap_clipped_regions * clipped_regions; BoxPtr extent; int i, j; - int width, height; RegionPtr current_region; int pixmap_width, pixmap_height; int m; @@ -400,8 +396,6 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, } extent = RegionExtents(region); - width = extent->x2 - extent->x1; - height = extent->y2 - extent->y1; /* Tile a large pixmap to another large pixmap. * We can't use the target large pixmap as the * loop variable, instead we need to loop for all @@ -462,13 +456,15 @@ _glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv, /* Construct a rect to clip the target region. */ repeat_box.x1 = shift_x + priv->box_array[idx].x1; repeat_box.y1 = shift_y + priv->box_array[idx].y1; - if (priv->block_wcnt == 1) + if (priv->block_wcnt == 1) { repeat_box.x2 = extent->x2; - else + dx = extent->x2 - repeat_box.x1; + } else repeat_box.x2 = shift_x + priv->box_array[idx].x2; - if (priv->block_hcnt == 1) + if (priv->block_hcnt == 1) { repeat_box.y2 = extent->y2; - else + dy = extent->y2 - repeat_box.y1; + } else repeat_box.y2 = shift_y + priv->box_array[idx].y2; current_region = RegionCreate(NULL, 4); @@ -980,16 +976,8 @@ glamor_composite_largepixmap_region(CARD8 op, glamor_pixmap_private * need_free_source_pixmap_priv = NULL; glamor_pixmap_private * need_free_mask_pixmap_priv = NULL; int source_repeat_type = 0, mask_repeat_type = 0; - PixmapPtr source_pixmap = NULL; - PixmapPtr mask_pixmap = NULL; int ok = TRUE; - if (source_pixmap_priv) - source_pixmap = source_pixmap_priv->base.pixmap; - - if (mask_pixmap_priv) - mask_pixmap = mask_pixmap_priv->base.pixmap; - if (source->repeat) source_repeat_type = source->repeatType; else From b8f0a2188295f6cc2c997b6639b6928323eae617 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 8 Aug 2012 20:11:43 +0800 Subject: [PATCH 431/462] Silence compilation warnings. After increase to gcc4.7, it reports more warnings, now fix them. Signed-off-by: Zhigang Gong Tested-by: Junyan He --- glamor/glamor_copyarea.c | 8 - glamor/glamor_copyplane.c | 3 - glamor/glamor_core.c | 8 +- glamor/glamor_egl.c | 11 +- glamor/glamor_eglmodule.c | 6 +- glamor/glamor_fbo.c | 2 - glamor/glamor_fillspans.c | 3 - glamor/glamor_glyphs.c | 55 ++--- glamor/glamor_gradient.c | 433 +++++++++++++++++------------------ glamor/glamor_picture.c | 6 - glamor/glamor_pixmap.c | 6 - glamor/glamor_polyfillrect.c | 3 - glamor/glamor_polylines.c | 2 - glamor/glamor_priv.h | 14 +- glamor/glamor_render.c | 7 +- glamor/glamor_trapezoid.c | 18 +- glamor/glamor_utils.h | 34 +-- 17 files changed, 281 insertions(+), 338 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 299417927..7d06833d6 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -392,14 +392,12 @@ _glamor_copy_n_to_n(DrawablePtr src, Bool upsidedown, Pixel bitplane, void *closure, Bool fallback) { - glamor_access_t dst_access; PixmapPtr dst_pixmap, src_pixmap; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; BoxPtr extent; RegionRec region; - ScreenPtr screen; int src_x_off, src_y_off, dst_x_off, dst_y_off; Bool ok = FALSE; int force_clip = 0; @@ -410,7 +408,6 @@ _glamor_copy_n_to_n(DrawablePtr src, dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - screen = dst_pixmap->drawable.pScreen; glamor_priv = glamor_get_screen_private(dst->pScreen); @@ -612,11 +609,6 @@ fall_back: glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); - if (gc && gc->alu != GXcopy) - dst_access = GLAMOR_ACCESS_RW; - else - dst_access = GLAMOR_ACCESS_WO; - if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c index 6487ff7fc..3f2652ac7 100644 --- a/glamor/glamor_copyplane.c +++ b/glamor/glamor_copyplane.c @@ -33,15 +33,12 @@ _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane, RegionPtr *pRegion, Bool fallback) { - glamor_screen_private *glamor_priv; - if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pSrc) && glamor_ddx_fallback_check_pixmap(pDst)) goto fail; - glamor_priv = glamor_get_screen_private(pDst->pScreen); glamor_prepare_access(pDst, GLAMOR_ACCESS_RW); glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO); *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 8ba3347d1..22065bc64 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -566,15 +566,13 @@ glamor_bitmap_to_region(PixmapPtr pixmap) /* Borrow from cairo. */ Bool -glamor_gl_has_extension(char *extension) +glamor_gl_has_extension(const char *extension) { - const char *gl_extensions; - char *pext; + const char *pext; int ext_len; ext_len = strlen(extension); - gl_extensions = (const char *) glGetString(GL_EXTENSIONS); - pext = (char *) gl_extensions; + pext = (const char*)glGetString(GL_EXTENSIONS); if (pext == NULL || extension == NULL) return FALSE; diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index a9a92a7f2..a248aa2e2 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -335,8 +335,6 @@ _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) } } -extern void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back); - _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) { @@ -399,16 +397,13 @@ static Bool glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, const char *extension) { - const char *egl_extensions; - char *pext; + const char *pext; int ext_len; - ext_len = strlen(extension); - egl_extensions = + ext_len = strlen(extension); + pext = (const char *) eglQueryString(glamor_egl->display, EGL_EXTENSIONS); - pext = (char *) egl_extensions; - if (pext == NULL || extension == NULL) return FALSE; while ((pext = strstr(pext, extension)) != NULL) { diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c index 046f4de5b..9a0dec9f2 100644 --- a/glamor/glamor_eglmodule.c +++ b/glamor/glamor_eglmodule.c @@ -31,10 +31,10 @@ #include "config.h" #endif -#define GLAMOR_FOR_XORG -#include "glamor.h" -#include #include +#define GLAMOR_FOR_XORG +#include +#include "glamor.h" static XF86ModuleVersionInfo VersRec = { GLAMOR_EGL_MODULE_NAME, diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 4af831d54..a46a740c8 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -258,7 +258,6 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) struct xorg_list *cache; glamor_pixmap_fbo *fbo_entry, *tmp; int i,j,k; - int empty_cache = TRUE; for(i = 0; i < CACHE_FORMAT_COUNT; i++) for(j = 0; j < CACHE_BUCKET_WCOUNT; j++) @@ -266,7 +265,6 @@ glamor_fbo_expire(glamor_screen_private *glamor_priv) cache = &glamor_priv->fbo_cache[i][j][k]; xorg_list_for_each_entry_safe_reverse(fbo_entry, tmp, cache, list) { if (GLAMOR_TICK_AFTER(fbo_entry->expire, glamor_priv->tick)) { - empty_cache = FALSE; break; } diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index 6598249fd..35e881f61 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -36,11 +36,8 @@ _glamor_fill_spans(DrawablePtr drawable, BoxPtr pbox; int x1, x2, y; RegionPtr pClip = fbGetCompositeClip(gc); - glamor_screen_private *glamor_priv; Bool ret = FALSE; - glamor_priv = glamor_get_screen_private(drawable->pScreen); - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index f5499049a..fc361df42 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -222,7 +222,7 @@ get_mask_cache(struct glamor_glyph_mask_cache *maskcache, int blocks) { int free_cleared_bit, idx = -1; int retry_cnt = 0; - unsigned int bits_mask; + unsigned int bits_mask = 0; if (maskcache->free_bitmap == 0) return NULL; @@ -514,20 +514,20 @@ glamor_glyph_priv_get_edge_map(GlyphPtr glyph, struct glamor_glyph *priv, PicturePtr glyph_picture) { PixmapPtr glyph_pixmap = (PixmapPtr) glyph_picture->pDrawable; - struct glamor_pixmap_private *pixmap_priv; int j; - unsigned long long left_x1_map, left_x2_map, right_x1_map, right_x2_map; + unsigned long long left_x1_map = 0, left_x2_map = 0; + unsigned long long right_x1_map = 0, right_x2_map = 0; int bitsPerPixel; int stride; void *bits; int width; - unsigned int left_x1_data, left_x2_data, right_x1_data, right_x2_data; + unsigned int left_x1_data = 0, left_x2_data = 0; + unsigned int right_x1_data = 0, right_x2_data = 0; bitsPerPixel = glyph_pixmap->drawable.bitsPerPixel; stride = glyph_pixmap->devKind; bits = glyph_pixmap->devPrivate.ptr; width = glyph->info.width; - pixmap_priv = glamor_get_pixmap_private(glyph_pixmap); if (glyph_pixmap->drawable.width < 2 || !(glyph_pixmap->drawable.depth == 8 @@ -662,12 +662,6 @@ glyph_new_fixed_list(struct glamor_glyph_list *fixed_list, fixed_list->list[list_cnt - 1].len = cur_pos - n_off; } else fixed_list->list[0].len = cur_pos - *head_pos - n_off; - while(list_cnt--) { - DEBUGF("new fixed list type %d entry len %d x %d y %d" - "head_pos %d pos %d list %d has %d glyphs.\n", - fixed_list->type, fixed_list->nlist, - cur_x, cur_y, *head_pos, cur_pos, i, fixed_list->list[i++].len); - } (*fixed_cnt)++; } @@ -712,9 +706,9 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, Bool first = TRUE, first_list = TRUE; Bool need_free_list_region = FALSE; Bool need_free_fixed_list = FALSE; - struct glamor_glyph *priv; + struct glamor_glyph *priv = NULL; Bool in_non_intersected_list = -1; - GlyphListPtr head_list, saved_list; + GlyphListPtr head_list; int head_x, head_y, head_pos; int fixed_cnt = 0; GlyphPtr *head_glyphs; @@ -732,9 +726,10 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, extents = pixman_region_extents(¤t_region); - saved_list = list; x = 0; y = 0; + x1 = x2 = y1 = y2 = 0; + n = 0; extents->x1 = 0; extents->y1 = 0; extents->x2 = 0; @@ -743,10 +738,10 @@ glamor_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs, head_list = list; DEBUGF("has %d lists.\n", nlist); while (nlist--) { - BoxRec left_box, right_box; + BoxRec left_box, right_box = {0}; Bool has_left_edge_box = FALSE, has_right_edge_box = FALSE; Bool left_to_right; - struct glamor_glyph *left_priv, *right_priv; + struct glamor_glyph *left_priv = NULL, *right_priv = NULL; x += list->xOff; y += list->yOff; @@ -1146,7 +1141,7 @@ glamor_glyph_cache(glamor_screen_private *glamor, GlyphPtr glyph, int *out_x, *out_y = priv->y; return cache->picture; } -typedef void (*glyphs_flush)(void * arg); +typedef void (*glyphs_flush_func)(void * arg); struct glyphs_flush_dst_arg { CARD8 op; PicturePtr src; @@ -1223,7 +1218,7 @@ glamor_buffer_glyph(glamor_screen_private *glamor_priv, int x_glyph, int y_glyph, int dx, int dy, int w, int h, int glyphs_dst_mode, - glyphs_flush glyphs_flush, void *flush_arg) + glyphs_flush_func glyphs_flush, void *flush_arg) { ScreenPtr screen = glamor_priv->screen; glamor_composite_rect_t *rect; @@ -1327,7 +1322,7 @@ glamor_buffer_glyph_clip(glamor_screen_private *glamor_priv, int glyph_dx, int glyph_dy, int width, int height, int glyphs_mode, - glyphs_flush flush_func, + glyphs_flush_func flush_func, void *arg ) { @@ -1490,24 +1485,24 @@ retry: glyph = *glyphs++; if (glyph->info.width > 0 && glyph->info.height > 0) { - glyphs_flush flush_func; - void *arg; + glyphs_flush_func flush_func; + void *temp_arg; if (need_free_mask) { if (pmask_buffer->count) - flush_func = (glyphs_flush)glamor_glyphs_flush_mask; + flush_func = (glyphs_flush_func)glamor_glyphs_flush_mask; else flush_func = NULL; - arg = pmask_arg; + temp_arg = pmask_arg; } else { /* If we are using global mask cache, then we need to * flush dst instead of mask. As some dst depends on the * previous mask result. Just flush mask can't get all previous's * overlapped glyphs.*/ if (dst_buffer.count || mask_buffer.count) - flush_func = (glyphs_flush)glamor_glyphs_flush_dst; + flush_func = (glyphs_flush_func)glamor_glyphs_flush_dst; else flush_func = NULL; - arg = &dst_arg; + temp_arg = &dst_arg; } glamor_buffer_glyph(glamor_priv, pmask_buffer, mask_format->format, @@ -1516,7 +1511,7 @@ retry: glyph->info.width, glyph->info.height, glyphs_dst_mode, flush_func, - (void*)arg); + (void*)temp_arg); } x += glyph->info.xOff; y += glyph->info.yOff; @@ -1538,7 +1533,7 @@ retry: glamor_destroy_pixmap(mask_pixmap); } else { struct glamor_glyph priv; - glyphs_flush flush_func; + glyphs_flush_func flush_func; BoxPtr rects; int nrect; @@ -1570,7 +1565,7 @@ retry: y += dst->pDrawable->y; if (dst_buffer.count || mask_buffer.count) - flush_func = (glyphs_flush)glamor_glyphs_flush_dst; + flush_func = (glyphs_flush_func)glamor_glyphs_flush_dst; else flush_func = NULL; @@ -1633,10 +1628,10 @@ glamor_glyphs_to_dst(CARD8 op, if (glyph->info.width > 0 && glyph->info.height > 0) { - glyphs_flush flush_func; + glyphs_flush_func flush_func; if (dst_buffer.count || mask_buffer.count) - flush_func = (glyphs_flush)glamor_glyphs_flush_dst; + flush_func = (glyphs_flush_func)glamor_glyphs_flush_dst; else flush_func = NULL; glamor_buffer_glyph_clip(glamor_priv, diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c index 444ba6cb9..4abc82d74 100644 --- a/glamor/glamor_gradient.c +++ b/glamor/glamor_gradient.c @@ -51,36 +51,36 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count, int use_ar char *gradient_fs = NULL; GLint fs_getcolor_prog; - const char *gradient_fs_getcolor = - GLAMOR_DEFAULT_PRECISION - "uniform int n_stop;\n" - "uniform float stops[%d];\n" - "uniform vec4 stop_colors[%d];\n" - "vec4 get_color(float stop_len)\n" - "{\n" - " int i = 0;\n" - " float new_alpha; \n" - " vec4 gradient_color;\n" - " float percentage; \n" - " for(i = 0; i < n_stop - 1; i++) {\n" - " if(stop_len < stops[i])\n" - " break; \n" - " }\n" - " \n" - " if(stops[i] - stops[i-1] > 2.0)\n" - " percentage = 0.0;\n" //For comply with pixman, walker->stepper overflow. - " else if(stops[i] - stops[i-1] < 0.000001)\n" - " percentage = 0.0;\n" - " else \n" - " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n" - " new_alpha = percentage * stop_colors[i].a + \n" - " (1.0-percentage) * stop_colors[i-1].a; \n" - " gradient_color = vec4((percentage * stop_colors[i].rgb \n" - " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n" - " new_alpha);\n" - " \n" - " return gradient_color;\n" - "}\n"; + #define gradient_fs_getcolor\ + GLAMOR_DEFAULT_PRECISION\ + "uniform int n_stop;\n"\ + "uniform float stops[%d];\n"\ + "uniform vec4 stop_colors[%d];\n"\ + "vec4 get_color(float stop_len)\n"\ + "{\n"\ + " int i = 0;\n"\ + " float new_alpha; \n"\ + " vec4 gradient_color;\n"\ + " float percentage; \n"\ + " for(i = 0; i < n_stop - 1; i++) {\n"\ + " if(stop_len < stops[i])\n"\ + " break; \n"\ + " }\n"\ + " \n"\ + " if(stops[i] - stops[i-1] > 2.0)\n"\ + " percentage = 0.0;\n" /*For comply with pixman, walker->stepper overflow.*/\ + " else if(stops[i] - stops[i-1] < 0.000001)\n"\ + " percentage = 0.0;\n"\ + " else \n"\ + " percentage = (stop_len - stops[i-1])/(stops[i] - stops[i-1]);\n"\ + " new_alpha = percentage * stop_colors[i].a + \n"\ + " (1.0-percentage) * stop_colors[i-1].a; \n"\ + " gradient_color = vec4((percentage * stop_colors[i].rgb \n"\ + " + (1.0-percentage) * stop_colors[i-1].rgb)*new_alpha, \n"\ + " new_alpha);\n"\ + " \n"\ + " return gradient_color;\n"\ + "}\n" /* Because the array access for shader is very slow, the performance is very low if use array. So use global uniform to replace for it if the number of n_stops is small.*/ @@ -238,111 +238,111 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dy * radius associated to it is negative (or it falls outside the valid t range) */ - const char *gradient_fs_template = - GLAMOR_DEFAULT_PRECISION - "uniform mat3 transform_mat;\n" - "uniform int repeat_type;\n" - "uniform float A_value;\n" - "uniform vec2 c1;\n" - "uniform float r1;\n" - "uniform vec2 c2;\n" - "uniform float r2;\n" - "varying vec2 source_texture;\n" - "\n" - "vec4 get_color(float stop_len);\n" - "\n" - "int t_invalid;\n" - "\n" - "float get_stop_len()\n" - "{\n" - " float t = 0.0;\n" - " float sqrt_value;\n" - " int revserse = 0;\n" - " t_invalid = 0;\n" - " \n" - " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" - " vec3 source_texture_trans = transform_mat * tmp;\n" - " source_texture_trans.xy = source_texture_trans.xy/source_texture_trans.z;\n" - " float B_value = (source_texture_trans.x - c1.x) * (c2.x - c1.x)\n" - " + (source_texture_trans.y - c1.y) * (c2.y - c1.y)\n" - " + r1 * (r2 - r1);\n" - " float C_value = (source_texture_trans.x - c1.x) * (source_texture_trans.x - c1.x)\n" - " + (source_texture_trans.y - c1.y) * (source_texture_trans.y - c1.y)\n" - " - r1*r1;\n" - " if(abs(A_value) < 0.00001) {\n" - " if(B_value == 0.0) {\n" - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " t = 0.5 * C_value / B_value;" - " } else {\n" - " sqrt_value = B_value * B_value - A_value * C_value;\n" - " if(sqrt_value < 0.0) {\n" - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " sqrt_value = sqrt(sqrt_value);\n" - " t = (B_value + sqrt_value) / A_value;\n" - " }\n" - " if(repeat_type == %d) {\n" // RepeatNone case. - " if((t <= 0.0) || (t > 1.0))\n" - // try another if first one invalid - " t = (B_value - sqrt_value) / A_value;\n" - " \n" - " if((t <= 0.0) || (t > 1.0)) {\n" //still invalid, return. - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " } else {\n" - " if(t * (r2 - r1) <= -1.0 * r1)\n" - // try another if first one invalid - " t = (B_value - sqrt_value) / A_value;\n" - " \n" - " if(t * (r2 -r1) <= -1.0 * r1) {\n" //still invalid, return. - " t_invalid = 1;\n" - " return t;\n" - " }\n" - " }\n" - " \n" - " if(repeat_type == %d){\n" // repeat normal - " while(t > 1.0) \n" - " t = t - 1.0; \n" - " while(t < 0.0) \n" - " t = t + 1.0; \n" - " }\n" - " \n" - " if(repeat_type == %d) {\n" // repeat reflect - " while(t > 1.0) {\n" - " t = t - 1.0; \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " while(t < 0.0) {\n" - " t = t + 1.0; \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " if(revserse == 1) {\n" - " t = 1.0 - t; \n" - " }\n" - " }\n" - " \n" - " return t;\n" + #define gradient_radial_fs_template\ + GLAMOR_DEFAULT_PRECISION\ + "uniform mat3 transform_mat;\n"\ + "uniform int repeat_type;\n"\ + "uniform float A_value;\n"\ + "uniform vec2 c1;\n"\ + "uniform float r1;\n"\ + "uniform vec2 c2;\n"\ + "uniform float r2;\n"\ + "varying vec2 source_texture;\n"\ + "\n"\ + "vec4 get_color(float stop_len);\n"\ + "\n"\ + "int t_invalid;\n"\ + "\n"\ + "float get_stop_len()\n"\ + "{\n"\ + " float t = 0.0;\n"\ + " float sqrt_value;\n"\ + " int revserse = 0;\n"\ + " t_invalid = 0;\n"\ + " \n"\ + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n"\ + " vec3 source_texture_trans = transform_mat * tmp;\n"\ + " source_texture_trans.xy = source_texture_trans.xy/source_texture_trans.z;\n"\ + " float B_value = (source_texture_trans.x - c1.x) * (c2.x - c1.x)\n"\ + " + (source_texture_trans.y - c1.y) * (c2.y - c1.y)\n"\ + " + r1 * (r2 - r1);\n"\ + " float C_value = (source_texture_trans.x - c1.x) * (source_texture_trans.x - c1.x)\n"\ + " + (source_texture_trans.y - c1.y) * (source_texture_trans.y - c1.y)\n"\ + " - r1*r1;\n"\ + " if(abs(A_value) < 0.00001) {\n"\ + " if(B_value == 0.0) {\n"\ + " t_invalid = 1;\n"\ + " return t;\n"\ + " }\n"\ + " t = 0.5 * C_value / B_value;"\ + " } else {\n"\ + " sqrt_value = B_value * B_value - A_value * C_value;\n"\ + " if(sqrt_value < 0.0) {\n"\ + " t_invalid = 1;\n"\ + " return t;\n"\ + " }\n"\ + " sqrt_value = sqrt(sqrt_value);\n"\ + " t = (B_value + sqrt_value) / A_value;\n"\ + " }\n"\ + " if(repeat_type == %d) {\n" /* RepeatNone case. */\ + " if((t <= 0.0) || (t > 1.0))\n"\ + /* try another if first one invalid*/\ + " t = (B_value - sqrt_value) / A_value;\n"\ + " \n"\ + " if((t <= 0.0) || (t > 1.0)) {\n" /*still invalid, return.*/\ + " t_invalid = 1;\n"\ + " return t;\n"\ + " }\n"\ + " } else {\n"\ + " if(t * (r2 - r1) <= -1.0 * r1)\n"\ + /* try another if first one invalid*/\ + " t = (B_value - sqrt_value) / A_value;\n"\ + " \n"\ + " if(t * (r2 -r1) <= -1.0 * r1) {\n" /*still invalid, return.*/\ + " t_invalid = 1;\n"\ + " return t;\n"\ + " }\n"\ + " }\n"\ + " \n"\ + " if(repeat_type == %d){\n" /* repeat normal*/\ + " while(t > 1.0) \n"\ + " t = t - 1.0; \n"\ + " while(t < 0.0) \n"\ + " t = t + 1.0; \n"\ + " }\n"\ + " \n"\ + " if(repeat_type == %d) {\n" /* repeat reflect*/\ + " while(t > 1.0) {\n"\ + " t = t - 1.0; \n"\ + " if(revserse == 0)\n"\ + " revserse = 1;\n"\ + " else\n"\ + " revserse = 0;\n"\ + " }\n"\ + " while(t < 0.0) {\n"\ + " t = t + 1.0; \n"\ + " if(revserse == 0)\n"\ + " revserse = 1;\n"\ + " else\n"\ + " revserse = 0;\n"\ + " }\n"\ + " if(revserse == 1) {\n"\ + " t = 1.0 - t; \n"\ + " }\n"\ + " }\n"\ + " \n"\ + " return t;\n"\ + "}\n"\ + "\n"\ + "void main()\n"\ + "{\n"\ + " float stop_len = get_stop_len();\n"\ + " if(t_invalid == 1) {\n"\ + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"\ + " } else {\n"\ + " gl_FragColor = get_color(stop_len);\n"\ + " }\n"\ "}\n" - "\n" - "void main()\n" - "{\n" - " float stop_len = get_stop_len();\n" - " if(t_invalid == 1) {\n" - " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" - " } else {\n" - " gl_FragColor = get_color(stop_len);\n" - " }\n" - "}\n"; glamor_priv = glamor_get_screen_private(screen); @@ -376,7 +376,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count, int dy GL_VERTEX_SHADER, gradient_vs); XNFasprintf(&gradient_fs, - gradient_fs_template, + gradient_radial_fs_template, PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT); fs_main_prog = glamor_compile_glsl_prog(dispatch, @@ -486,89 +486,88 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count, int dy * before and after it. Use the interpolation fomula to compute RGBA. */ - const char *gradient_fs_template = - GLAMOR_DEFAULT_PRECISION - "uniform mat3 transform_mat;\n" - "uniform int repeat_type;\n" - "uniform int hor_ver;\n" - "uniform float pt_slope;\n" - "uniform float cos_val;\n" - "uniform float p1_distance;\n" - "uniform float pt_distance;\n" - "varying vec2 source_texture;\n" - "\n" - "vec4 get_color(float stop_len);\n" - "\n" - "float get_stop_len()\n" - "{\n" - " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n" - " float len_percentage;\n" - " float distance;\n" - " float _p1_distance;\n" - " float _pt_distance;\n" - " float y_dist;\n" - " float stop_after;\n" - " float stop_before;\n" - " vec4 stop_color_before;\n" - " vec4 stop_color_after;\n" - " float new_alpha; \n" - " int revserse = 0;\n" - " vec4 gradient_color;\n" - " float percentage; \n" - " vec3 source_texture_trans = transform_mat * tmp;\n" - " \n" - " if(hor_ver == 0) { \n" //Normal case. - " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n" - " distance = y_dist * cos_val;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " \n" - " } else if (hor_ver == 1) {\n"//horizontal case. - " distance = source_texture_trans.x;\n" - " _p1_distance = p1_distance * source_texture_trans.z;\n" - " _pt_distance = pt_distance * source_texture_trans.z;\n" - " } \n" - " \n" - " distance = distance - _p1_distance; \n" - " \n" - " if(repeat_type == %d){\n" // repeat normal - " while(distance > _pt_distance) \n" - " distance = distance - (_pt_distance); \n" - " while(distance < 0.0) \n" - " distance = distance + (_pt_distance); \n" - " }\n" - " \n" - " if(repeat_type == %d) {\n" // repeat reflect - " while(distance > _pt_distance) {\n" - " distance = distance - (_pt_distance); \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " while(distance < 0.0) {\n" - " distance = distance + (_pt_distance); \n" - " if(revserse == 0)\n" - " revserse = 1;\n" - " else\n" - " revserse = 0;\n" - " }\n" - " if(revserse == 1) {\n" - " distance = (_pt_distance) - distance; \n" - " }\n" - " }\n" - " \n" - " len_percentage = distance/(_pt_distance);\n" - " \n" - " return len_percentage;\n" + #define gradient_fs_template \ + GLAMOR_DEFAULT_PRECISION\ + "uniform mat3 transform_mat;\n"\ + "uniform int repeat_type;\n"\ + "uniform int hor_ver;\n"\ + "uniform float pt_slope;\n"\ + "uniform float cos_val;\n"\ + "uniform float p1_distance;\n"\ + "uniform float pt_distance;\n"\ + "varying vec2 source_texture;\n"\ + "\n"\ + "vec4 get_color(float stop_len);\n"\ + "\n"\ + "float get_stop_len()\n"\ + "{\n"\ + " vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n"\ + " float len_percentage;\n"\ + " float distance;\n"\ + " float _p1_distance;\n"\ + " float _pt_distance;\n"\ + " float y_dist;\n"\ + " float stop_after;\n"\ + " float stop_before;\n"\ + " vec4 stop_color_before;\n"\ + " vec4 stop_color_after;\n"\ + " float new_alpha; \n"\ + " int revserse = 0;\n"\ + " vec4 gradient_color;\n"\ + " float percentage; \n"\ + " vec3 source_texture_trans = transform_mat * tmp;\n"\ + " \n"\ + " if(hor_ver == 0) { \n" /*Normal case.*/\ + " y_dist = source_texture_trans.y - source_texture_trans.x*pt_slope;\n"\ + " distance = y_dist * cos_val;\n"\ + " _p1_distance = p1_distance * source_texture_trans.z;\n"\ + " _pt_distance = pt_distance * source_texture_trans.z;\n"\ + " \n"\ + " } else if (hor_ver == 1) {\n"/*horizontal case.*/\ + " distance = source_texture_trans.x;\n"\ + " _p1_distance = p1_distance * source_texture_trans.z;\n"\ + " _pt_distance = pt_distance * source_texture_trans.z;\n"\ + " } \n"\ + " \n"\ + " distance = distance - _p1_distance; \n"\ + " \n"\ + " if(repeat_type == %d){\n" /* repeat normal*/\ + " while(distance > _pt_distance) \n"\ + " distance = distance - (_pt_distance); \n"\ + " while(distance < 0.0) \n"\ + " distance = distance + (_pt_distance); \n"\ + " }\n"\ + " \n"\ + " if(repeat_type == %d) {\n" /* repeat reflect*/\ + " while(distance > _pt_distance) {\n"\ + " distance = distance - (_pt_distance); \n"\ + " if(revserse == 0)\n"\ + " revserse = 1;\n"\ + " else\n"\ + " revserse = 0;\n"\ + " }\n"\ + " while(distance < 0.0) {\n"\ + " distance = distance + (_pt_distance); \n"\ + " if(revserse == 0)\n"\ + " revserse = 1;\n"\ + " else\n"\ + " revserse = 0;\n"\ + " }\n"\ + " if(revserse == 1) {\n"\ + " distance = (_pt_distance) - distance; \n"\ + " }\n"\ + " }\n"\ + " \n"\ + " len_percentage = distance/(_pt_distance);\n"\ + " \n"\ + " return len_percentage;\n"\ + "}\n"\ + "\n"\ + "void main()\n"\ + "{\n"\ + " float stop_len = get_stop_len();\n"\ + " gl_FragColor = get_color(stop_len);\n"\ "}\n" - "\n" - "void main()\n" - "{\n" - " float stop_len = get_stop_len();\n" - " gl_FragColor = get_color(stop_len);\n" - "}\n"; - glamor_priv = glamor_get_screen_private(screen); diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c index 44e1e40d7..7d5ffbb76 100644 --- a/glamor/glamor_picture.c +++ b/glamor/glamor_picture.c @@ -73,13 +73,10 @@ 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); if (!pixmap_priv) { @@ -112,13 +109,10 @@ 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); diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index f3a2a87ab..9bbc989cb 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -926,7 +926,6 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format, glamor_pixmap_private *pixmap_priv; GLenum gl_access = 0, gl_usage = 0; void *data, *read; - ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; @@ -936,7 +935,6 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format, int fbo_x_off, fbo_y_off; data = bits; - screen = pixmap->drawable.pScreen; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return NULL; @@ -1193,13 +1191,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) glamor_get_pixmap_private(pixmap); unsigned int stride; void *data = NULL, *dst; - ScreenPtr screen; glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch; int pbo = 0; - screen = pixmap->drawable.pScreen; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return TRUE; @@ -1259,7 +1255,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) { - glamor_screen_private *glamor_priv; glamor_pixmap_fbo *old_fbo; glamor_pixmap_fbo *new_fbo = NULL; PixmapPtr scratch = NULL; @@ -1274,7 +1269,6 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) return TRUE; old_fbo = pixmap_priv->base.fbo; - glamor_priv = pixmap_priv->base.glamor_priv; if (!old_fbo) return FALSE; diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 738e8eb11..4e1f7b3a9 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -43,9 +43,6 @@ _glamor_poly_fill_rect(DrawablePtr drawable, register BoxPtr pbox; RegionPtr pClip = fbGetCompositeClip(gc); Bool ret = FALSE; - glamor_screen_private *glamor_priv; - - glamor_priv = glamor_get_screen_private(drawable->pScreen); xorg = drawable->x; yorg = drawable->y; diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c index 70dd6c161..e723e9500 100644 --- a/glamor/glamor_polylines.c +++ b/glamor/glamor_polylines.c @@ -45,7 +45,6 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, xRectangle *rects; int x1, x2, y1, y2; int i; - glamor_screen_private *glamor_priv; /* Don't try to do wide lines or non-solid fill style. */ if (gc->lineWidth != 0) { @@ -105,7 +104,6 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, && glamor_ddx_fallback_check_gc(gc)) return FALSE; - glamor_priv = glamor_get_screen_private(drawable->pScreen); if (gc->lineWidth == 0) { if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 1830b56ee..03ef6cce8 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -549,9 +549,6 @@ extern int glamor_debug_level; /* glamor.c */ PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); -PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, - unsigned int usage); - Bool glamor_destroy_pixmap(PixmapPtr pixmap); glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv); @@ -568,16 +565,12 @@ void glamor_init_pixmap_fbo(ScreenPtr screen); void glamor_fini_pixmap_fbo(ScreenPtr screen); Bool glamor_pixmap_fbo_fixup(ScreenPtr screen, PixmapPtr pixmap); void glamor_fbo_expire(glamor_screen_private *glamor_priv); -void glamor_init_pixmap_fbo(ScreenPtr screen); -void glamor_fini_pixmap_fbo(ScreenPtr screen); glamor_pixmap_fbo * glamor_create_fbo_array(glamor_screen_private *glamor_priv, int w, int h, GLenum format, int flag, int block_w, int block_h, glamor_pixmap_private *); -Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); - /* glamor_copyarea.c */ RegionPtr glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, @@ -603,7 +596,6 @@ void glamor_fini_finish_access_shaders(ScreenPtr screen); const Bool glamor_get_drawable_location(const DrawablePtr drawable); void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap, int *x, int *y); -Bool glamor_create_gc(GCPtr gc); Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, @@ -636,7 +628,7 @@ Bool glamor_set_alu(struct glamor_gl_dispatch *dispatch, Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask); Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask); RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap); -Bool glamor_gl_has_extension(char *extension); +Bool glamor_gl_has_extension(const char *extension); int glamor_gl_get_version(void); #define GLAMOR_GL_VERSION_ENCODE(major, minor) ( \ @@ -683,7 +675,6 @@ void glamor_glyphs(CARD8 op, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); -void glamor_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph); /* glamor_setspans.c */ void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int n, int sorted); @@ -947,9 +938,6 @@ void glamor_finish_access_picture(PicturePtr picture, glamor_access_t access); void glamor_destroy_picture(PicturePtr picture); -enum glamor_pixmap_status - glamor_upload_picture_to_texture(PicturePtr picture); - /* fixup a fbo to the exact size as the pixmap. */ Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 9b80295e5..27d5dc58c 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -43,6 +43,7 @@ //#define DEBUGRegionPrint(x) do {} while (0) #define DEBUGRegionPrint RegionPrint #endif + static struct blendinfo composite_op_info[] = { [PictOpClear] = {0, 0, GL_ZERO, GL_ZERO}, [PictOpSrc] = {0, 0, GL_ONE, GL_ZERO}, @@ -1715,7 +1716,7 @@ _glamor_composite(CARD8 op, glamor_get_screen_private(screen); Bool ret = TRUE; RegionRec region; - BoxPtr box, extent; + BoxPtr extent; int nbox, ok = FALSE; PixmapPtr sub_dest_pixmap = NULL; PixmapPtr sub_source_pixmap = NULL; @@ -1778,7 +1779,6 @@ _glamor_composite(CARD8 op, goto done; } - box = REGION_RECTS(®ion); nbox = REGION_NUM_RECTS(®ion); DEBUGF("first clipped when compositing.\n"); DEBUGRegionPrint(®ion); @@ -1833,6 +1833,7 @@ _glamor_composite(CARD8 op, x_dest, y_dest); REGION_UNINIT(dest->pDrawable->pScreen, ®ion); + if (ok) goto done; fail: @@ -1886,7 +1887,7 @@ fail: GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); if (mask && mask->pDrawable && !mask->transform) GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); -full_fallback: + if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (source_pixmap == dest_pixmap || glamor_prepare_access_picture (source, GLAMOR_ACCESS_RO)) { diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 7bb75f59b..57a178cb6 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -81,12 +81,16 @@ _glamor_lines_crossfixedY (xLineFixed *l, xLineFixed *r) xFixed dy2 = r->p2.y - r->p1.y; xFixed_32_32 tmp = (xFixed_32_32) dy2 * dy1; xFixed_32_32 dividend1 = (tmp >> 32) * (l->p1.x - r->p1.x); + xFixed_32_32 dividend2; + xFixed_32_32 dividend3; + xFixed_32_32 divisor; + tmp = (xFixed_32_32) dx1 * dy2; - xFixed_32_32 dividend2 = (tmp >> 32) * l->p1.y; + dividend2 = (tmp >> 32) * l->p1.y; tmp = (xFixed_32_32) dy1 * dx2; - xFixed_32_32 dividend3 = (tmp >> 32) * r->p1.y; - xFixed_32_32 divisor = ((xFixed_32_32) dx1 * (xFixed_32_32) dy2 - - (xFixed_32_32) dy1 * (xFixed_32_32) dx2) >> 32; + dividend3 = (tmp >> 32) * r->p1.y; + divisor = ((xFixed_32_32) dx1 * (xFixed_32_32) dy2 + - (xFixed_32_32) dy1 * (xFixed_32_32) dx2) >> 32; if (divisor) return (xFixed)((dividend2 - dividend1 - dividend3) / divisor); @@ -1363,7 +1367,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, glamor_pixmap_private *pixmap_priv; PixmapPtr pixmap = NULL; GLint trapezoid_prog; - float width, height; GLfloat xscale, yscale; float left_slope, right_slope; xTrapezoid *ptrap; @@ -1399,9 +1402,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale)); - width = (float)(bounds->x2 - bounds->x1); - height = (float)(bounds->y2 - bounds->y1); - dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -1604,11 +1604,11 @@ glamor_create_mask_picture(ScreenPtr screen, static int _glamor_trapezoid_bounds (int ntrap, xTrapezoid *traps, BoxPtr box) { + int has_large_trapezoid = 0; box->y1 = MAXSHORT; box->y2 = MINSHORT; box->x1 = MAXSHORT; box->x2 = MINSHORT; - int has_large_trapezoid = 0; for (; ntrap; ntrap--, traps++) { INT16 x1, y1, x2, y2; diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 6eef722ba..36beb49ed 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -39,12 +39,12 @@ #define t_from_x_coord_y(_yscale_, _y_) (1.0 - (_y_) * (_yscale_)) #define t_from_x_coord_y_inverted(_yscale_, _y_) ((_y_) * (_yscale_)) -#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_)\ - do { \ - int w,h; \ - PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \ - *(_pxscale_) = 1.0 / w; \ - *(_pyscale_) = 1.0 / h; \ +#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ + do { \ + int _w_,_h_; \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, _w_, _h_); \ + *(_pxscale_) = 1.0 / _w_; \ + *(_pyscale_) = 1.0 / _h_; \ } while(0) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ @@ -302,14 +302,14 @@ #define glamor_transform_point(matrix, tx, ty, x, y) \ do { \ - int i; \ - float result[4]; \ - for (i = 0; i < 3; i++) { \ - result[i] = (matrix)[i * 3] * (x) + (matrix)[i * 3 + 1] * (y) \ - + (matrix)[i * 3 + 2]; \ + int _i_; \ + float _result_[4]; \ + for (_i_ = 0; _i_ < 3; _i_++) { \ + _result_[_i_] = (matrix)[_i_ * 3] * (x) + (matrix)[_i_ * 3 + 1] * (y) \ + + (matrix)[_i_ * 3 + 2]; \ } \ - tx = result[0] / result[2]; \ - ty = result[1] / result[2]; \ + tx = _result_[0] / _result_[2]; \ + ty = _result_[1] / _result_[2]; \ } while(0) #define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_, \ @@ -734,10 +734,10 @@ #define glamor_set_const_ext(params, nparam, vertices, nverts, stride) \ do { \ - int i = 0, j = 0; \ - for(; i < nverts; i++) { \ - for(j = 0; j < nparam; j++) { \ - vertices[stride*i + j] = params[j]; \ + int _i_ = 0, _j_ = 0; \ + for(; _i_ < nverts; _i_++) { \ + for(_j_ = 0; _j_ < nparam; _j_++) { \ + vertices[stride*_i_ + _j_] = params[_j_]; \ } \ } \ } while(0) From e846f48f489e33e270db682b1b6c8e6f03fdf313 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Wed, 8 Aug 2012 20:43:38 +0800 Subject: [PATCH 432/462] Increase vbo size to 64K verts. This commit will benefit vertex stressing cases such as aa10text/rgb10text, and can get about 15% performance gain. Signed-off-by: Zhigang Gong Acked-by: Junyan --- glamor/glamor_fill.c | 1 - glamor/glamor_priv.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 1d81aea52..2f08d7275 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -220,7 +220,6 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color) } } -#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 if (unlikely(nbox > 1)) dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo); diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 03ef6cce8..6e80ebdf9 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -191,7 +191,7 @@ enum glamor_gl_flavor { #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2 -#define GLAMOR_COMPOSITE_VBO_VERT_CNT 1024 +#define GLAMOR_COMPOSITE_VBO_VERT_CNT (64*1024) typedef struct { PicturePtr picture; /* Where the glyphs of the cache are stored */ From 14e02f5132d7b4f50c8d9f8e5c6a0f285a3f3c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 31 Oct 2012 16:56:00 +0100 Subject: [PATCH 433/462] Don't use glBlitFramebufferEXT for overlapping copies. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the GL_EXT_framebuffer_blit spec, the result of doing so is undefined. But we need well-defined results. :) Signed-off-by: Michel Dänzer --- glamor/glamor_copyarea.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index 7d06833d6..4e6f953d2 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -318,7 +318,8 @@ __glamor_copy_n_to_n(DrawablePtr src, dx, dy, src_pixmap, dst_pixmap); #ifndef GLAMOR_GLES2 - if ((overlaped || glamor_priv->state != RENDER_STATE + if (!overlaped && + (glamor_priv->state != RENDER_STATE || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { From 80f5e21daeed79654d6e1976f2766eb528f01d47 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 13 Nov 2012 10:08:02 +0800 Subject: [PATCH 434/462] glamor_compositerects: Need to initialize region before fallback. As we need to call DamageRegionAppend even for fallback path, we must initialize the region before do that. Pointed by Igor Vagulin. https://bugs.freedesktop.org/show_bug.cgi?id=56940 Signed-off-by: Zhigang Gong --- glamor/glamor_compositerects.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_compositerects.c b/glamor/glamor_compositerects.c index 5fe1bbf77..f1564a258 100644 --- a/glamor/glamor_compositerects.c +++ b/glamor/glamor_compositerects.c @@ -131,16 +131,6 @@ glamor_composite_rectangles(CARD8 op, return; } - pixmap = glamor_get_drawable_pixmap(dst->pDrawable); - priv = glamor_get_pixmap_private(pixmap); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) - goto fallback; - if (dst->alphaMap) { - DEBUGF("%s: fallback, dst has an alpha-map\n", __FUNCTION__); - goto fallback; - } - if ((color->red|color->green|color->blue|color->alpha) <= 0x00ff) { switch (op) { case PictOpOver: @@ -204,6 +194,16 @@ glamor_composite_rectangles(CARD8 op, return; } + pixmap = glamor_get_drawable_pixmap(dst->pDrawable); + priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) + goto fallback; + if (dst->alphaMap) { + DEBUGF("%s: fallback, dst has an alpha-map\n", __FUNCTION__); + goto fallback; + } + need_free_region = TRUE; DEBUGF("%s: drawable extents (%d, %d),(%d, %d) x %d\n", From efbdc9e90f36494b07508aeaba40c9eb01eab398 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 29 Dec 2012 06:28:17 +0000 Subject: [PATCH 435/462] glamor: fix make distcheck part 1 This just adds the headers, then it falls over on the sdk_HEADERS as it overrides proper install paths by the looks of it. Signed-off-by: Dave Airlie --- glamor/Makefile.am | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 766aac776..e1ee86d90 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -20,10 +20,13 @@ AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) libglamor_la_LDFLAGS = -avoid-version libglamor_la_SOURCES = \ + compat-api.h \ glamor.c \ glamor_copyarea.c \ glamor_copywindow.c \ glamor_core.c \ + glamor_debug.h \ + glamor_gl_dispatch.h \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ @@ -42,6 +45,7 @@ libglamor_la_SOURCES = \ glamor_copyplane.c\ glamor_glyphblt.c\ glamor_polyops.c\ + glamor_priv.h\ glamor_pixmap.c\ glamor_largepixmap.c\ glamor_picture.c\ @@ -49,7 +53,9 @@ libglamor_la_SOURCES = \ glamor_gl_dispatch.c\ glamor_fbo.c\ glamor_compositerects.c\ - glamor.h + glamor_utils.h\ + glamor.h\ + glapi.h sdk_HEADERS = glamor.h From 6b954880c25af353dd4679cfdad6664b107d4df6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 29 Dec 2012 06:42:10 +0000 Subject: [PATCH 436/462] glamor: add compiler.h This is also required for distchecking. Signed-off-by: Dave Airlie --- glamor/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index e1ee86d90..55721f645 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -21,6 +21,7 @@ libglamor_la_LDFLAGS = -avoid-version libglamor_la_SOURCES = \ compat-api.h \ + compiler.h \ glamor.c \ glamor_copyarea.c \ glamor_copywindow.c \ From 4c5bfd529f6f182a3f0ac1b9bb5c3170a297f460 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 29 Dec 2012 06:42:30 +0000 Subject: [PATCH 437/462] glamor_utils: fix unlikely define use using a define across a split line expression is failure, compiling with warnings shows this up. Signed-off-by: Dave Airlie --- glamor/glamor_utils.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index 36beb49ed..d30783826 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -80,8 +80,7 @@ #define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_) \ do { \ - if (unlikely(_priv_ && (_priv_)->type \ - == GLAMOR_TEXTURE_LARGE)) { \ + if (unlikely(_priv_ && (_priv_)->type == GLAMOR_TEXTURE_LARGE)) { \ *(_xoff_) = - (_priv_)->large.box.x1; \ *(_yoff_) = - (_priv_)->large.box.y1; \ } else { \ From 97416e3f144606728a963aa2a337b1283e156ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 13 Mar 2013 17:15:33 +0100 Subject: [PATCH 438/462] glamoregl: Use xf86ScreenToScrn() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes crashes when glamor is used for a GPU screen with xserver 1.13 or newer. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57200#c17 Signed-off-by: Michel Dänzer Reviewed-by: Chris Wilson --- glamor/glamor_egl.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index a248aa2e2..cd0bdc09c 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -116,7 +116,7 @@ glamor_egl_get_screen_private(ScrnInfoPtr scrn) _X_EXPORT void glamor_egl_make_current(ScreenPtr screen) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); @@ -139,7 +139,7 @@ glamor_egl_make_current(ScreenPtr screen) _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); @@ -221,7 +221,7 @@ glamor_create_texture_from_image(struct glamor_egl_screen_private Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; PixmapPtr screen_pixmap; @@ -245,7 +245,7 @@ glamor_egl_create_textured_screen_ext(ScreenPtr screen, int stride, PixmapPtr *back_pixmap) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; glamor_egl = glamor_egl_get_screen_private(scrn); @@ -272,7 +272,7 @@ Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) { ScreenPtr screen = pixmap->drawable.pScreen; - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; EGLImageKHR image; GLuint texture; @@ -318,7 +318,7 @@ done: static void _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) { - ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); EGLImageKHR image; struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); @@ -338,7 +338,7 @@ _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) { - ScrnInfoPtr scrn = xf86Screens[front->drawable.pScreen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(front->drawable.pScreen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); EGLImageKHR old_front_image; @@ -371,7 +371,7 @@ glamor_egl_close_screen(CLOSE_SCREEN_ARGS_DECL) PixmapPtr screen_pixmap; EGLImageKHR back_image; - scrn = xf86Screens[screen->myNum]; + scrn = xf86ScreenToScrn(screen); glamor_egl = glamor_egl_get_screen_private(scrn); screen_pixmap = screen->GetScreenPixmap(screen); @@ -417,7 +417,7 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl, void glamor_egl_screen_init(ScreenPtr screen) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); @@ -588,7 +588,7 @@ glamor_gl_dispatch_init(ScreenPtr screen, struct glamor_gl_dispatch *dispatch, int gl_version) { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(scrn); if (!glamor_gl_dispatch_init_impl From fc179bb863778c03288bebaa258358ccbdb6aa0c Mon Sep 17 00:00:00 2001 From: Armin K Date: Wed, 13 Mar 2013 18:28:57 +0100 Subject: [PATCH 439/462] Silence Automake 1.13 warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS') Reviewed-by: Michel Dänzer --- glamor/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 55721f645..2140b8147 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -12,7 +12,7 @@ endif instdir = $(moduledir) -INCLUDES = \ +AM_CPPFLAGS = \ $(XORG_INCS) AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) From b0318b6de7a2f8c5d9e75b55211dcc0b12f811fc Mon Sep 17 00:00:00 2001 From: Armin K Date: Wed, 13 Mar 2013 18:28:58 +0100 Subject: [PATCH 440/462] Properly dist necesary headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Michel Dänzer --- glamor/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 2140b8147..0879287fe 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -31,6 +31,7 @@ libglamor_la_SOURCES = \ glamor_fill.c \ glamor_fillspans.c \ glamor_getspans.c \ + glamor_glext.h \ glamor_glyphs.c \ glamor_polyfillrect.c \ glamor_polylines.c \ From 7e818f7d39cfef2701fe9cf95c7854ee8c9f3be6 Mon Sep 17 00:00:00 2001 From: Armin K Date: Wed, 13 Mar 2013 18:49:32 +0100 Subject: [PATCH 441/462] First attempt to make libglamor.so shared versioned library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As recommended by Michel in this thread reply: http://lists.freedesktop.org/archives/glamor/2013-March/000305.html v2: Correct shared library location in glamor.pc.in Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=62259 Reviewed-by: Michel Dänzer --- glamor/Makefile.am | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 0879287fe..4beb5591c 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -1,4 +1,4 @@ -inst_LTLIBRARIES = libglamor.la +lib_LTLIBRARIES = libglamor.la # Override these since glamor doesn't need them and the needed files aren't # built (in hw/xfree86/os-support/solaris) until after glamor is built @@ -10,14 +10,12 @@ else libglamor_la_LIBADD = $(GL_LIBS) endif -instdir = $(moduledir) - AM_CPPFLAGS = \ $(XORG_INCS) AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) -libglamor_la_LDFLAGS = -avoid-version +libglamor_la_LDFLAGS = -version-info 0:0:0 libglamor_la_SOURCES = \ compat-api.h \ @@ -65,7 +63,8 @@ if EGL LIBGLAMOREGL = libglamoregl.la module_LTLIBRARIES = $(LIBGLAMOREGL) libglamoregl_la_DEPENDENCIES = libglamor.la -libglamoregl_la_LDFLAGS = -avoid-version -module $(EGL_LIBS) -lglamor $(GLX_SYS_LIBS) +libglamoregl_la_LDFLAGS = -avoid-version -module +libglamoregl_la_LIBADD = $(EGL_LIBS) $(GLX_SYS_LIBS) libglamor.la libglamoregl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c libglamoregl_la_CFLAGS = $(AM_CFLAGS) $(GLX_DEFINES) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) endif From 2ea618f2cf906fec9807b321f9e8ef3a4706c708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 26 Aug 2013 14:57:47 +0800 Subject: [PATCH 442/462] Use GBM_LIBS and GBM_CFLAGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König Reviewed-by: Michel Dänzer --- glamor/Makefile.am | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 4beb5591c..c1759c6c5 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -64,9 +64,15 @@ LIBGLAMOREGL = libglamoregl.la module_LTLIBRARIES = $(LIBGLAMOREGL) libglamoregl_la_DEPENDENCIES = libglamor.la libglamoregl_la_LDFLAGS = -avoid-version -module -libglamoregl_la_LIBADD = $(EGL_LIBS) $(GLX_SYS_LIBS) libglamor.la +libglamoregl_la_LIBADD = $(EGL_LIBS) $(GLX_SYS_LIBS) $(GBM_LIBS) libglamor.la libglamoregl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c -libglamoregl_la_CFLAGS = $(AM_CFLAGS) $(GLX_DEFINES) -I$(top_srcdir)/src $(LIBDRM_CFLAGS) $(EGL_CFLAGS) +libglamoregl_la_CFLAGS = \ + $(AM_CFLAGS) \ + $(GLX_DEFINES) \ + -I$(top_srcdir)/src \ + $(LIBDRM_CFLAGS) \ + $(EGL_CFLAGS) \ + $(GBM_CFLAGS) endif From 61fca4342a65be2dbc7f890f2e67da56a50db978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 17 Sep 2013 13:25:02 +0200 Subject: [PATCH 443/462] Fix RegionContainsRect test for PutImage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return value of RegionContainsRect() is not a boolean but an enum indicating that the region contains the rectangle completely, partially or not at all. We can only take the PutImage fastpath when the region contatins the rectangle completely. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65964 Signed-off-by: Michel Dänzer Reviewed-by: Zhigang Gong --- glamor/glamor_putimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 34e86a147..6567f1406 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -287,7 +287,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, box.x2 = x + w + drawable->x; box.y2 = y + h + drawable->y; - if ((clip != NULL && !RegionContainsRect(clip, &box)) + if ((clip != NULL && RegionContainsRect(clip, &box) != rgnIN) || gc->alu != GXcopy) { temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); if (temp_pixmap == NULL) From 39e95cd0f50cf471d8220d5428788d5be6a59d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 20 Sep 2013 10:41:10 +0200 Subject: [PATCH 444/462] Reset traps_count and ptrap when necessary for the next trapezoid cliprect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64912 Signed-off-by: Michel Dänzer Reviewed-by: He Junyan Reviewed-by: Zhigang Gong --- glamor/glamor_trapezoid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 57a178cb6..7c934e346 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -934,6 +934,9 @@ NTRAPS_LOOP_AGAIN: traps_not_completed -= traps_count; glamor_flush_composite_triangles(screen); goto NTRAPS_LOOP_AGAIN; + } else { + ptrap = traps; + traps_count = ntrap; } pbox++; From e3d1d4e3caaab8076eba89b58d037d24e203e506 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 23 Sep 2013 06:42:24 +0100 Subject: [PATCH 445/462] glamor: add initial Xv support This does YV12 and I420 for now, not sure if we can do packed without a GL extension. Signed-off-by: Dave Airlie Reviewed-by: Alex Deucher --- glamor/Makefile.am | 1 + glamor/glamor.c | 6 + glamor/glamor.h | 4 +- glamor/glamor_priv.h | 27 ++ glamor/glamor_xv.c | 646 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 683 insertions(+), 1 deletion(-) create mode 100644 glamor/glamor_xv.c diff --git a/glamor/Makefile.am b/glamor/Makefile.am index c1759c6c5..50cfe97ea 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -53,6 +53,7 @@ libglamor_la_SOURCES = \ glamor_gl_dispatch.c\ glamor_fbo.c\ glamor_compositerects.c\ + glamor_xv.c\ glamor_utils.h\ glamor.h\ glapi.h diff --git a/glamor/glamor.c b/glamor/glamor.c index d51811e5d..7637f3bfe 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -427,6 +427,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_init_finish_access_shaders(screen); #ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); +#endif +#ifdef GLAMOR_XV + glamor_init_xv_shader(screen); #endif glamor_pixmap_init(screen); @@ -447,6 +450,9 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_screen_private *glamor_priv; glamor_priv = glamor_get_screen_private(screen); +#ifdef GLAMOR_XV + glamor_fini_xv_shader(screen); +#endif #ifdef RENDER glamor_fini_composite_shaders(screen); #endif diff --git a/glamor/glamor.h b/glamor/glamor.h index bafd543b5..c143c4dcb 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -37,7 +37,7 @@ #include #include #include - +#include /* * glamor_pixmap_type : glamor pixmap's type. * @MEMORY: pixmap is in memory. @@ -348,4 +348,6 @@ extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC, int extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr points); +extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen, int num_texture_ports); + #endif /* GLAMOR_H */ diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 6e80ebdf9..ffdd7fdd0 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -304,6 +304,9 @@ typedef struct glamor_screen_private { int state; unsigned int render_idle_cnt; ScreenPtr screen; + + /* xv */ + GLint xv_prog; } glamor_screen_private; typedef enum glamor_access { @@ -993,6 +996,30 @@ glamor_composite_rectangles(CARD8 op, int num_rects, xRectangle *rects); +/* glamor_xv */ +typedef struct { + uint32_t transform_index; + uint32_t gamma; /* gamma value x 1000 */ + int brightness; + int saturation; + int hue; + int contrast; + + DrawablePtr pDraw; + PixmapPtr pPixmap; + uint32_t src_pitch; + uint8_t *src_addr; + int src_w, src_h, dst_w, dst_h; + int src_x, src_y, drw_x, drw_y; + int w, h; + RegionRec clip; + PixmapPtr src_pix[3]; /* y, u, v for planar */ + int src_pix_w, src_pix_h; +} glamor_port_private; + +void glamor_init_xv_shader(ScreenPtr screen); +void glamor_fini_xv_shader(ScreenPtr screen); + #include"glamor_utils.h" /* Dynamic pixmap upload to texture if needed. diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c new file mode 100644 index 000000000..1d77eaa65 --- /dev/null +++ b/glamor/glamor_xv.c @@ -0,0 +1,646 @@ +/* + * Copyright © 2013 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Dave Airlie + * + * some code is derived from the xf86-video-ati radeon driver, mainly + * the calculations. + */ + +/** @file glamor_xv.c + * + * Xv acceleration implementation + */ + +#include "glamor_priv.h" + +#ifdef GLAMOR_XV +#include "xf86xv.h" +#include +#include "fourcc.h" +/* Reference color space transform data */ +typedef struct tagREF_TRANSFORM +{ + float RefLuma; + float RefRCb; + float RefRCr; + float RefGCb; + float RefGCr; + float RefBCb; + float RefBCr; +} REF_TRANSFORM; + +#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0) +#define RTFBrightness(a) (((a)*1.0)/2000.0) +#define RTFIntensity(a) (((a)*1.0)/2000.0) +#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) +#define RTFHue(a) (((a)*3.1416)/1000.0) + +static const char *xv_vs= "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "varying vec2 tcs;\n" + "void main()\n" "{\n" " gl_Position = v_position;\n" + "tcs = v_texcoord0.xy;\n" + "}\n"; + +static const char *xv_ps = GLAMOR_DEFAULT_PRECISION + "uniform sampler2D y_sampler;\n" + "uniform sampler2D u_sampler;\n" + "uniform sampler2D v_sampler;\n" + "uniform vec4 offsetyco;\n" + "uniform vec4 ucogamma;\n" + "uniform vec4 vco;\n" + "varying vec2 tcs;\n" + "float sample;\n" + "vec4 temp1;\n" + "void main()\n" "{\n" + "sample = texture2D(y_sampler, tcs).w;\n" + "temp1.xyz = offsetyco.www * vec3(sample) + offsetyco.xyz;\n" + "sample = texture2D(u_sampler, tcs).w;\n" + "temp1.xyz = ucogamma.xyz * vec3(sample) + temp1.xyz;\n" + "sample = texture2D(v_sampler, tcs).w;\n" + "temp1.xyz = clamp(vco.xyz * vec3(sample) + temp1.xyz, 0.0, 1.0);\n" + "temp1.w = 1.0;\n" + "gl_FragColor = temp1;\n" + "}\n"; + +void +glamor_init_xv_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + GLint fs_prog, vs_prog; + GLint sampler_loc; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + glamor_priv->xv_prog = dispatch->glCreateProgram(); + + vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, xv_vs); + fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, xv_ps); + dispatch->glAttachShader(glamor_priv->xv_prog, vs_prog); + dispatch->glAttachShader(glamor_priv->xv_prog, fs_prog); + + dispatch->glBindAttribLocation(glamor_priv->xv_prog, + GLAMOR_VERTEX_POS, "v_position"); + dispatch->glBindAttribLocation(glamor_priv->xv_prog, + GLAMOR_VERTEX_SOURCE, "v_texcoord0"); + glamor_link_glsl_prog(dispatch, glamor_priv->xv_prog); + + glamor_put_dispatch(glamor_priv); +} + +void +glamor_fini_xv_shader(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + + glamor_priv = glamor_get_screen_private(screen); + dispatch = glamor_get_dispatch(glamor_priv); + + dispatch->glDeleteProgram(glamor_priv->xv_prog); + glamor_put_dispatch(glamor_priv); +} + +#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvContrast, xvSaturation, xvHue, xvColorspace, xvGamma; + +#define NUM_ATTRIBUTES 5 +static XF86AttributeRec Attributes_glamor[NUM_ATTRIBUTES+1] = +{ + {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, + {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, + {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, + {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, + {0, 0, 0, NULL} + }; + +#define NUM_FORMATS 3 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} + }; + +#define NUM_IMAGES 2 + +static XF86ImageRec Images[NUM_IMAGES] = +{ +XVIMAGE_YV12, + XVIMAGE_I420, + }; + +static void +glamor_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) +{ +glamor_port_private *port_priv = (glamor_port_private *)data; +int i; +if (!cleanup) + return; + +for (i = 0; i < 3; i++) { +if (port_priv->src_pix[i]) { +glamor_destroy_pixmap(port_priv->src_pix[i]); +port_priv->src_pix[i] = NULL; +} +} +} + +static int +glamor_xv_set_port_attribute(ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data) +{ +glamor_port_private *port_priv = (glamor_port_private *)data; +if (attribute == xvBrightness) + port_priv->brightness = ClipValue(value, -1000, 1000); +else if (attribute == xvHue) + port_priv->hue = ClipValue(value, -1000, 1000); +else if (attribute == xvContrast) + port_priv->contrast = ClipValue(value, -1000, 1000); +else if (attribute == xvSaturation) + port_priv->saturation = ClipValue(value, -1000, 1000); +else if (attribute == xvGamma) + port_priv->gamma = ClipValue (value, 100, 10000); +else if(attribute == xvColorspace) + port_priv->transform_index = ClipValue (value, 0, 1); +else + return BadMatch; +return Success; +} + +static int +glamor_xv_get_port_attribute(ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data) +{ +glamor_port_private *port_priv = (glamor_port_private *)data; +if (attribute == xvBrightness) + *value = port_priv->brightness; +else if (attribute == xvHue) + *value = port_priv->hue; +else if (attribute == xvContrast) + *value = port_priv->contrast; +else if (attribute == xvSaturation) + *value = port_priv->saturation; +else if (attribute == xvGamma) + *value = port_priv->gamma; +else if(attribute == xvColorspace) + *value = port_priv->transform_index; +else + return BadMatch; + +return Success; +} + +static void +glamor_xv_query_best_size(ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data) +{ +*p_w = drw_w; +*p_h = drw_h; +} + +static int +glamor_xv_query_image_attributes(ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ +int size = 0, tmp; + +if (offsets) offsets[0] = 0; +switch (id) { +case FOURCC_YV12: +case FOURCC_I420: +*h = *h; +*w = *w; +size = *w; +if (pitches) pitches[0] = size; +size *= *h; +if (offsets) offsets[1] = size; +tmp = *w >> 1; +if (pitches) pitches[1] = pitches[2] = tmp; +tmp *= (*h >> 1); +size += tmp; +if (offsets) offsets[2] = size; +size += tmp; +break; +} +return size; +} +/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces + note the difference to the parameters used in overlay are due + to 10bit vs. float calcs */ +static REF_TRANSFORM trans[2] = +{ + {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */ + {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0} /* BT.709 */ + }; + +static void +glamor_display_textured_video(glamor_port_private *port_priv) +{ +ScreenPtr screen = port_priv->pPixmap->drawable.pScreen; +glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); +glamor_pixmap_private *pixmap_priv = + glamor_get_pixmap_private(port_priv->pPixmap); +glamor_pixmap_private *src_pixmap_priv[3]; +glamor_gl_dispatch *dispatch; +float vertices[32], texcoords[8]; +BoxPtr box = REGION_RECTS(&port_priv->clip); +int nBox = REGION_NUM_RECTS(&port_priv->clip); +int dst_x_off, dst_y_off; +GLfloat dst_xscale, dst_yscale; +GLfloat src_xscale[3], src_yscale[3]; +int i; +const float Loff = -0.0627; +const float Coff = -0.502; +float uvcosf, uvsinf; +float yco; +float uco[3], vco[3], off[3]; +float bright, cont, gamma; +int ref = port_priv->transform_index; +GLint uloc, sampler_loc; + +cont = RTFContrast(port_priv->contrast); +bright = RTFBrightness(port_priv->brightness); +gamma = (float)port_priv->gamma / 1000.0; +uvcosf = RTFSaturation(port_priv->saturation) * cos(RTFHue(port_priv->hue)); +uvsinf = RTFSaturation(port_priv->saturation) * sin(RTFHue(port_priv->hue)); +/* overlay video also does pre-gamma contrast/sat adjust, should we? */ + +yco = trans[ref].RefLuma * cont; +uco[0] = -trans[ref].RefRCr * uvsinf; +uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf; +uco[2] = trans[ref].RefBCb * uvcosf; +vco[0] = trans[ref].RefRCr * uvcosf; +vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf; +vco[2] = trans[ref].RefBCb * uvsinf; +off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright; +off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright; +off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright; +gamma = 1.0; + +pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale); +glamor_get_drawable_deltas(port_priv->pDraw, port_priv->pPixmap, &dst_x_off, + &dst_y_off); +glamor_set_destination_pixmap_priv_nc(pixmap_priv); + +for (i = 0; i < 3; i++) { +if (port_priv->src_pix[i]) { +src_pixmap_priv[i] = glamor_get_pixmap_private(port_priv->src_pix[i]); +pixmap_priv_get_scale(src_pixmap_priv[i], &src_xscale[i], &src_yscale[i]); +} +} +dispatch = glamor_get_dispatch(glamor_priv); +dispatch->glUseProgram(glamor_priv->xv_prog); + +uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "offsetyco"); +dispatch->glUniform4f(uloc, off[0], off[1], off[2], yco); +uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "ucogamma"); +dispatch->glUniform4f(uloc, uco[0], uco[1], uco[2], gamma); +uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "vco"); +dispatch->glUniform4f(uloc, vco[0], vco[1], vco[2], 0); + +dispatch->glActiveTexture(GL_TEXTURE0); +dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->base.fbo->tex); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + +dispatch->glActiveTexture(GL_TEXTURE1); +dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->base.fbo->tex); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + +dispatch->glActiveTexture(GL_TEXTURE2); +dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->base.fbo->tex); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); +dispatch->glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + +sampler_loc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "y_sampler"); +dispatch->glUniform1i(sampler_loc, 0); +sampler_loc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "u_sampler"); +dispatch->glUniform1i(sampler_loc, 1); +sampler_loc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "v_sampler"); +dispatch->glUniform1i(sampler_loc, 2); + +dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, + GL_FLOAT, GL_FALSE, + 2 * sizeof(float), + texcoords); +dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + +dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + +dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); +for (i = 0; i < nBox; i++) { +float off_x = box[i].x1 - port_priv->drw_x; +float off_y = box[i].y1 - port_priv->drw_y; +float diff_x = (float)port_priv->src_w / (float)port_priv->dst_w; +float diff_y = (float)port_priv->src_h / (float)port_priv->dst_h; +float srcx, srcy, srcw, srch; +int dstx, dsty, dstw, dsth; + + +dstx = box[i].x1 + dst_x_off; +dsty = box[i].y1 + dst_y_off; +dstw = box[i].x2 - box[i].x1; +dsth = box[i].y2 - box[i].y1; + +srcx = port_priv->src_x + off_x * diff_x; +srcy = port_priv->src_y + off_y * diff_y; +srcw = (port_priv->src_w * dstw) / (float)port_priv->dst_w; +srch = (port_priv->src_h * dsth) / (float)port_priv->dst_h; + +glamor_set_normalize_vcoords(pixmap_priv, + dst_xscale, dst_yscale, + dstx, + dsty, + dstx + dstw, + dsty + dsth, + glamor_priv->yInverted, + vertices); + +glamor_set_normalize_tcoords(src_pixmap_priv[0], + src_xscale[0], + src_yscale[0], + srcx, + srcy, + srcx + srcw, + srcy + srch, + glamor_priv->yInverted, + texcoords); + +dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); +dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); + +dispatch->glUseProgram(0); +glamor_put_dispatch(glamor_priv); +DamageDamageRegion(port_priv->pDraw, &port_priv->clip); +} + +static int glamor_xv_put_image(ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, + unsigned char *buf, + short width, + short height, + Bool sync, + RegionPtr clipBoxes, + pointer data, + DrawablePtr pDrawable) +{ + ScreenPtr screen = xf86ScrnToScreen(pScrn); + glamor_port_private *port_priv = (glamor_port_private *)data; + INT32 x1, x2, y1, y2; + int srcPitch, srcPitch2; + BoxRec dstBox; + int top, nlines; + int s2offset, s3offset, tmp; + + s2offset = s3offset = srcPitch2 = 0; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) + return Success; + + if ((x1 >= x2) || (y1 >= y2)) + return Success; + + srcPitch = width; + srcPitch2 = width >> 1; + + if (!port_priv->src_pix[0] || (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) { + int i; + for (i = 0; i < 2; i++) + if (port_priv->src_pix[i]) + glamor_destroy_pixmap(port_priv->src_pix[i]); + + port_priv->src_pix[0] = glamor_create_pixmap(screen, width, height, 8, 0); + port_priv->src_pix[1] = glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0); + port_priv->src_pix[2] = glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0); + port_priv->src_pix_w = width; + port_priv->src_pix_h = height; + + if (!port_priv->src_pix[0] || !port_priv->src_pix[1] || !port_priv->src_pix[2]) + return BadAlloc; + } + + top = (y1 >> 16) & ~1; + nlines = ((y2 + 0xffff) >> 16) - top; + + switch (id) { + case FOURCC_YV12: + case FOURCC_I420: + s2offset = srcPitch * height; + s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1)); + s2offset += ((top >> 1) * srcPitch2); + s3offset += ((top >> 1) * srcPitch2); + if (id == FOURCC_YV12) { + tmp = s2offset; + s2offset = s3offset; + s3offset = tmp; + } + glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0], + 0, 0, srcPitch, nlines, + port_priv->src_pix[0]->devKind, + buf + (top * srcPitch), 0); + + glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1], + 0, 0, srcPitch2, (nlines + 1) >> 1, + port_priv->src_pix[1]->devKind, + buf + s2offset, 0); + + glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2], + 0, 0, srcPitch2, (nlines + 1) >> 1, + port_priv->src_pix[2]->devKind, + buf + s3offset, 0); + break; + default: + return BadMatch; + } + + if (pDrawable->type == DRAWABLE_WINDOW) + port_priv->pPixmap = (*screen->GetWindowPixmap)((WindowPtr)pDrawable); + else + port_priv->pPixmap = (PixmapPtr)pDrawable; + + if (!RegionEqual(&port_priv->clip, clipBoxes)) { + RegionCopy(&port_priv->clip, clipBoxes); + } + + port_priv->src_x = src_x; + port_priv->src_y = src_y; + port_priv->src_w = src_w; + port_priv->src_h = src_h; + port_priv->dst_w = drw_w; + port_priv->dst_h = drw_h; + port_priv->drw_x = drw_x; + port_priv->drw_y = drw_y; + port_priv->w = width; + port_priv->h = height; + port_priv->pDraw = pDrawable; + glamor_display_textured_video(port_priv); + return Success; +} + +static XF86VideoEncodingRec DummyEncodingGLAMOR[1] = +{ + { + 0, + "XV_IMAGE", + 8192, 8192, + {1, 1} + } +}; + +XF86VideoAdaptorPtr +glamor_xv_init(ScreenPtr screen, int num_texture_ports) +{ + glamor_port_private *port_priv; + XF86VideoAdaptorPtr adapt; + int i; + + adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports * + (sizeof(glamor_port_private) + sizeof(DevUnion))); + if (adapt == NULL) + return NULL; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvHue = MAKE_ATOM("XV_HUE"); + xvGamma = MAKE_ATOM("XV_GAMMA"); + xvColorspace = MAKE_ATOM("XV_COLORSPACE"); + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = 0; + adapt->name = "GLAMOR Textured Video"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncodingGLAMOR; + + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = num_texture_ports; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + adapt->pAttributes = Attributes_glamor; + adapt->nAttributes = NUM_ATTRIBUTES; + + port_priv = (glamor_port_private *)(&adapt->pPortPrivates[num_texture_ports]); + adapt->pImages = Images; + adapt->nImages = NUM_IMAGES; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = glamor_xv_stop_video; + adapt->SetPortAttribute = glamor_xv_set_port_attribute; + adapt->GetPortAttribute = glamor_xv_get_port_attribute; + adapt->QueryBestSize = glamor_xv_query_best_size; + adapt->PutImage = glamor_xv_put_image; + adapt->ReputImage = NULL; + adapt->QueryImageAttributes = glamor_xv_query_image_attributes; + + for (i = 0; i < num_texture_ports; i++) { + glamor_port_private *pPriv = &port_priv[i]; + + pPriv->brightness = 0; + pPriv->contrast = 0; + pPriv->saturation = 0; + pPriv->hue = 0; + pPriv->gamma = 1000; + pPriv->transform_index = 0; + + REGION_NULL(pScreen, &pPriv->clip); + + adapt->pPortPrivates[i].ptr = (pointer)(pPriv); + } + return adapt; +} +#else +XF86VideoAdaptorPtr +glamor_xv_init(ScreenPtr screen, int num_texture_ports) +{ + return NULL; +} +#endif From 229601e080aefad21927c1449cd520733317858b Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 27 Sep 2013 05:25:54 +0800 Subject: [PATCH 446/462] Shoud return null subpixmap if we fail to get a valid map address. The patch is prepared by Raul Fernandes. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86693 Signed-off-by: Zhigang Gong --- glamor/glamor_pixmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index 9bbc989cb..84694ec3c 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -1377,6 +1377,10 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind, data, pbo, access); + if(data == NULL) { + fbDestroyPixmap(sub_pixmap); + return NULL; + } if (pbo) { assert(sub_pixmap->devPrivate.ptr == NULL); sub_pixmap->devPrivate.ptr = data; From 8afa008ec4b393666bb3c506a711b4d50cc4e756 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Wed, 2 Oct 2013 00:37:55 +0200 Subject: [PATCH 447/462] Use glDrawRangeElements instead of glDrawElements This lets us explicitly specify the range of vertices that are used, which the OpenGL driver can use for optimization. Particularly, it results in lower CPU overhead with Mesa-based drivers. Reviewed-by: Alex Deucher Reviewed-by: Zhigang Gong --- glamor/glamor_fill.c | 9 +++++++++ glamor/glamor_gl_dispatch.c | 1 + glamor/glamor_gl_dispatch.h | 1 + glamor/glamor_render.c | 6 ++++++ glamor/glamor_trapezoid.c | 6 ++++++ 5 files changed, 23 insertions(+) diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c index 2f08d7275..fbc87392e 100644 --- a/glamor/glamor_fill.c +++ b/glamor/glamor_fill.c @@ -244,10 +244,19 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color) if (box_cnt == 1) dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4); else +#ifndef GLAMOR_GLES2 + dispatch->glDrawRangeElements(GL_TRIANGLES, + 0, + box_cnt * 4, + box_cnt * 6, + GL_UNSIGNED_SHORT, + NULL); +#else dispatch->glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT, NULL); +#endif nbox -= box_cnt; box += box_cnt; } diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c index f99650425..da99e2627 100644 --- a/glamor/glamor_gl_dispatch.c +++ b/glamor/glamor_gl_dispatch.c @@ -54,6 +54,7 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch, INIT_FUNC(dispatch, glMapBufferRange, get_proc_address); INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address); INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address); + INIT_FUNC(dispatch, glDrawRangeElements, get_proc_address); #endif INIT_FUNC(dispatch, glViewport, get_proc_address); INIT_FUNC(dispatch, glDrawArrays, get_proc_address); diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h index b3fc3a629..76dadd49e 100644 --- a/glamor/glamor_gl_dispatch.h +++ b/glamor/glamor_gl_dispatch.h @@ -12,6 +12,7 @@ typedef struct glamor_gl_dispatch { /* Elements Array*/ void (*glDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); + void (*glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices); /* Raster functions */ void (*glReadPixels) (GLint x, GLint y, diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 27d5dc58c..d2ac38103 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -841,8 +841,14 @@ glamor_flush_composite_rects(ScreenPtr screen) if (!glamor_priv->render_nr_verts) return; +#ifndef GLAMOR_GLES2 + dispatch->glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts, + (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); +#else dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, GL_UNSIGNED_SHORT, NULL); +#endif glamor_put_dispatch(glamor_priv); } diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c index 7c934e346..76b3729cf 100644 --- a/glamor/glamor_trapezoid.c +++ b/glamor/glamor_trapezoid.c @@ -1543,8 +1543,14 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture, glamor_priv->vb, GL_DYNAMIC_DRAW); } +#ifndef GLAMOR_GLES2 + dispatch->glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts, + (glamor_priv->render_nr_verts * 3) / 2, + GL_UNSIGNED_SHORT, NULL); +#else dispatch->glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2, GL_UNSIGNED_SHORT, NULL); +#endif } dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0); From 5695708ecd2a26fcb9c05985c6758e719071995a Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Wed, 2 Oct 2013 00:37:56 +0200 Subject: [PATCH 448/462] Use GL_STATIC_DRAW for element index buffer The buffer never changes anyway. Reviewed-by: Alex Deucher Reviewed-by: Zhigang Gong --- glamor/glamor_render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index d2ac38103..ca8e509da 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -408,7 +408,7 @@ glamor_init_composite_shaders(ScreenPtr screen) if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, - NULL, GL_DYNAMIC_DRAW); + NULL, GL_STATIC_DRAW); eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); } else { @@ -428,7 +428,7 @@ glamor_init_composite_shaders(ScreenPtr screen) } else { dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, - eb, GL_DYNAMIC_DRAW); + eb, GL_STATIC_DRAW); dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); From 2f62bd46cc002af57f8fe3246b9aea9e0c0bbcc9 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Wed, 2 Oct 2013 00:37:57 +0200 Subject: [PATCH 449/462] glamor_render: fix PictFilters Add Fast/Good/Best and appropriately map to Nearest and Bilinear. Additionally, add a fallback path for unsupported filters. Notably, this fixes window shadow rendering with Compiz, which uses PictFilterConvolution for some odd reason. Reviewed-by: Alex Deucher Reviewed-by: Zhigang Gong --- glamor/glamor_render.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index ca8e509da..76a571f8b 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -568,6 +568,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, switch (picture->filter) { default: + case PictFilterFast: case PictFilterNearest: dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -576,6 +577,8 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; + case PictFilterGood: + case PictFilterBest: case PictFilterBilinear: dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, @@ -1771,6 +1774,12 @@ _glamor_composite(CARD8 op, } } + if ((source && source->filter >= PictFilterConvolution) + || (mask && mask->filter >= PictFilterConvolution)) { + glamor_fallback("glamor_composite(): unsupported filter\n"); + goto fail; + } + if (!miComputeCompositeRegion(®ion, source, mask, dest, x_source + (source_pixmap ? source->pDrawable->x : 0), From 3bf1eb577e2d2b4d55d38b5a0043b0efb9abb385 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sat, 19 Oct 2013 16:10:52 -0600 Subject: [PATCH 450/462] Fix _glamor_set_spans() bug (re-used 'n' variable) n was used as a function parameter. But inside the for (i=1..n) loop, n got reassigned as REGION_NUM_RECTS() and then decremented to zero by the while loop. This caused the for loop to only iterate once instead of 'n' times. This patch renames the n parameter to numPoints. Found by code inspection. Untested. Reviewed-by: Zhigang Gong --- glamor/glamor_setspans.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c index a71efe901..3d447b606 100644 --- a/glamor/glamor_setspans.c +++ b/glamor/glamor_setspans.c @@ -30,7 +30,7 @@ static Bool _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted, + DDXPointPtr points, int *widths, int numPoints, int sorted, Bool fallback) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); @@ -53,9 +53,9 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, goto fail; glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); - for (i = 0; i < n; i++) { + for (i = 0; i < numPoints; i++) { - n = REGION_NUM_RECTS(clip); + int n = REGION_NUM_RECTS(clip); pbox = REGION_RECTS(clip); while (n--) { int x1 = points[i].x; @@ -85,7 +85,7 @@ fail: 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); + fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } ret = TRUE; From 8c51eb8239247c98057eb9daf06c905a1dc0588c Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sat, 19 Oct 2013 16:10:53 -0600 Subject: [PATCH 451/462] Remove redundant dispatch->glEnable(GL_TEXTURE_2D) The same call was already made a few lines earlier. Reviewed-by: Zhigang Gong --- glamor/glamor_putimage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c index 6567f1406..99f7ac6f5 100644 --- a/glamor/glamor_putimage.c +++ b/glamor/glamor_putimage.c @@ -181,7 +181,6 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - dispatch->glEnable(GL_TEXTURE_2D); /* Now that we've set up our bitmap texture and the shader, shove * the destination rectangle through the cliprects and run the From 644e05562e401f192c93964be06c33fe92099089 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sat, 19 Oct 2013 16:10:54 -0600 Subject: [PATCH 452/462] Remove useless return statement Reviewed-by: Zhigang Gong --- glamor/glamor_getimage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c index f446c8333..5df576c45 100644 --- a/glamor/glamor_getimage.c +++ b/glamor/glamor_getimage.c @@ -90,7 +90,6 @@ glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d) { _glamor_get_image(pDrawable, x, y, w, h, format, planeMask, d, TRUE); - return; } Bool From 2925db6616944c8d1e911caee0637a00e5586576 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Sat, 2 Nov 2013 00:08:11 +0800 Subject: [PATCH 453/462] Fixed an incorrect printf format. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69573 Signed-off-by: Zhigang Gong --- glamor/glamor_fbo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index a46a740c8..4838a277f 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -212,7 +212,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) break; } - FatalError("destination is framebuffer incomplete: %s [%#x]\n", + FatalError("destination is framebuffer incomplete: %s [%x]\n", str, status); } glamor_put_dispatch(fbo->glamor_priv); From 842cd7eb4353492bc9c29439f975c3bd33445cbd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 6 Nov 2013 10:25:27 +0100 Subject: [PATCH 454/462] fixup picture in SetWindowPixmap When creating a window with recordmydesktop running, the following may happen: create picture 0x1cd457e0, with drawable 0x1327d1f0 (SetWindowPixmap is called) destroy picture 0x1cd457e0, with drawable 0x1cd65820 Obtaining format for pixmap 0x1327d1f0 and picture 0x1cd457e0 ==7989== Invalid read of size 4 ==7989== at 0x8CAA0CA: glamor_get_tex_format_type_from_pixmap (glamor_utils.h:1252) ==7989== by 0x8CAD1B7: glamor_download_sub_pixmap_to_cpu (glamor_pixmap.c:1074) ==7989== by 0x8CA8BB7: _glamor_get_image (glamor_getimage.c:66) ==7989== by 0x8CA8D2F: glamor_get_image (glamor_getimage.c:92) ==7989== by 0x29AEF2: miSpriteGetImage (misprite.c:413) ==7989== by 0x1E7674: compGetImage (compinit.c:148) ==7989== by 0x1F5E5B: ProcShmGetImage (shm.c:684) ==7989== by 0x1F686F: ProcShmDispatch (shm.c:1121) ==7989== by 0x15D00D: Dispatch (dispatch.c:432) ==7989== by 0x14C569: main (main.c:298) ==7989== Address 0x1cd457f0 is 16 bytes inside a block of size 120 free'd ==7989== at 0x4C2B60C: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7989== by 0x228897: FreePicture (picture.c:1477) ==7989== by 0x228B23: PictureDestroyWindow (picture.c:73) ==7989== by 0x234C19: damageDestroyWindow (damage.c:1646) ==7989== by 0x1E92C0: compDestroyWindow (compwindow.c:590) ==7989== by 0x20FF85: DbeDestroyWindow (dbe.c:1389) ==7989== by 0x185D46: FreeWindowResources (window.c:907) ==7989== by 0x1889A7: DeleteWindow (window.c:975) ==7989== by 0x17EBF1: doFreeResource (resource.c:873) ==7989== by 0x17FC1B: FreeClientResources (resource.c:1139) ==7989== by 0x15C4DE: CloseDownClient (dispatch.c:3402) ==7989== by 0x2AB843: CheckConnections (connection.c:1008) ==7989== (II) fail to get matched format for dfdfdfdf The fix is to update the picture pointer when the window pixmap is changed, so it moves the picture around with the window rather than the pixmap. This makes FreePicture work correctly. Signed-off-by: Maarten Lankhorst Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71088 Reviewed-by: Zhigang Gong --- glamor/glamor.c | 4 ++++ glamor/glamor_compositerects.c | 4 ++-- glamor/glamor_priv.h | 3 +++ glamor/glamor_window.c | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 7637f3bfe..e8e68be53 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -413,6 +413,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_priv->saved_procs.create_picture = ps->CreatePicture; ps->CreatePicture = glamor_create_picture; + glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; + screen->SetWindowPixmap = glamor_set_window_pixmap; + glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture; ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); @@ -531,6 +534,7 @@ glamor_close_screen(CLOSE_SCREEN_ARGS_DECL) ps->CompositeRects = glamor_priv->saved_procs.composite_rects; ps->Glyphs = glamor_priv->saved_procs.glyphs; ps->UnrealizeGlyph = glamor_priv->saved_procs.unrealize_glyph; + screen->SetWindowPixmap = glamor_priv->saved_procs.set_window_pixmap; #endif screen_pixmap = screen->GetScreenPixmap(screen); glamor_set_pixmap_private(screen_pixmap, NULL); diff --git a/glamor/glamor_compositerects.c b/glamor/glamor_compositerects.c index f1564a258..1a5769958 100644 --- a/glamor/glamor_compositerects.c +++ b/glamor/glamor_compositerects.c @@ -215,8 +215,8 @@ glamor_composite_rectangles(CARD8 op, if (dst->pCompositeClip->data && (!pixman_region_intersect(®ion, ®ion, dst->pCompositeClip) || region_is_empty(®ion))) { - DEBUGF(("%s: zero-intersection between rectangles and clip\n", - __FUNCTION__)); + DEBUGF("%s: zero-intersection between rectangles and clip\n", + __FUNCTION__); pixman_region_fini(®ion); return; } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index ffdd7fdd0..b6a1075ad 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -221,6 +221,7 @@ struct glamor_saved_procs { CreatePictureProcPtr create_picture; DestroyPictureProcPtr destroy_picture; UnrealizeGlyphProcPtr unrealize_glyph; + SetWindowPixmapProcPtr set_window_pixmap; }; #ifdef GLAMOR_GLES2 @@ -934,6 +935,8 @@ void glamor_destroy_upload_pixmap(PixmapPtr pixmap); int glamor_create_picture(PicturePtr picture); +void glamor_set_window_pixmap(WindowPtr pWindow, PixmapPtr pPixmap); + Bool glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access); diff --git a/glamor/glamor_window.c b/glamor/glamor_window.c index 3da11e447..b67c72880 100644 --- a/glamor/glamor_window.c +++ b/glamor/glamor_window.c @@ -69,3 +69,35 @@ glamor_change_window_attributes(WindowPtr pWin, unsigned long mask) } return TRUE; } + +void +glamor_set_window_pixmap(WindowPtr win, PixmapPtr pPixmap) +{ + ScreenPtr screen = win->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + PixmapPtr old = screen->GetWindowPixmap(win); + + if (pPixmap != old) { + glamor_pixmap_private *pixmap_priv; + PicturePtr pic = NULL; + + pixmap_priv = glamor_get_pixmap_private(old); + if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) && pixmap_priv->base.picture->pDrawable == (DrawablePtr)win) { + pic = pixmap_priv->base.picture; + pixmap_priv->base.is_picture = 0; + pixmap_priv->base.picture = NULL; + } + + pixmap_priv = glamor_get_pixmap_private(pPixmap); + if (pixmap_priv) { + pixmap_priv->base.is_picture = !!pic; + pixmap_priv->base.picture = pic; + } + } + + screen->SetWindowPixmap = glamor_priv->saved_procs.set_window_pixmap; + (screen->SetWindowPixmap)(win, pPixmap); + glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; + screen->SetWindowPixmap = glamor_set_window_pixmap; +} From 403004fe799f293bf299fe78da821635b19d9a1a Mon Sep 17 00:00:00 2001 From: Fabio Pedretti Date: Mon, 4 Nov 2013 12:08:42 +0100 Subject: [PATCH 455/462] glamor: remove unused variable Reviewed-by: Zhigang Gong --- glamor/glamor_xv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c index 1d77eaa65..8f12c1f1e 100644 --- a/glamor/glamor_xv.c +++ b/glamor/glamor_xv.c @@ -90,7 +90,6 @@ glamor_init_xv_shader(ScreenPtr screen) glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; GLint fs_prog, vs_prog; - GLint sampler_loc; glamor_priv = glamor_get_screen_private(screen); dispatch = glamor_get_dispatch(glamor_priv); From a5321ea431376feca2dcd55cf04925dc492270fc Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Mon, 18 Nov 2013 22:52:22 +0100 Subject: [PATCH 456/462] Allow to create textured pixmaps from gbm_bo without using gem names This implements glamor_egl_create_textured_pixmap_from_gbm_bo, which is similar to glamor_egl_create_textured_pixmap, except it takes a gbm_bo as argument. Signed-off-by: Axel Davy Reviewed-by: Zhigang Gong --- glamor/glamor.h | 13 +++++++++++++ glamor/glamor_egl.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/glamor/glamor.h b/glamor/glamor.h index c143c4dcb..927892fd6 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -230,6 +230,19 @@ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride); +/* + * @glamor_egl_create_textured_pixmap_from_bo: Try to create a textured pixmap + * from a gbm_bo. + * + * @pixmap: The pixmap need to be processed. + * @bo: a pointer on a gbm_bo structure attached to this pixmap at DDX layer. + * + * This function is similar to glamor_egl_create_textured_pixmap. + */ +extern _X_EXPORT Bool + glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, + void *bo); + extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); #endif diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index cd0bdc09c..50b764b6a 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -315,6 +315,40 @@ done: return ret; } +Bool +glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl; + EGLImageKHR image; + GLuint texture; + Bool ret = FALSE; + + glamor_egl = glamor_egl_get_screen_private(scrn); + + glamor_egl_make_current(screen); + + image = glamor_egl->egl_create_image_khr(glamor_egl->display, + glamor_egl->context, + EGL_NATIVE_PIXMAP_KHR, + bo, NULL); + if (image == EGL_NO_IMAGE_KHR) { + glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); + goto done; + } + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); + glamor_set_pixmap_texture(pixmap, texture); + dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, + image); + ret = TRUE; + +done: + glamor_egl_restore_context(screen); + return ret; +} + static void _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) { From 06ba3fdfd6162a64c149ea6fda85f9f56d7f3c31 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 19 Nov 2013 15:16:57 +0800 Subject: [PATCH 457/462] Fixed some compilation warning/error or error checking. There is one compilation error ,cast int to pointer, when built without libgbm, reported by Gaetan Nadon. And some error checking after memory allocation, reported by Seth Arnold. There are still some similar issues in the largepixmap implementation. They are relatively more complicate due to the heavy usage of RegionXXX APIs which may allocate implicitly. Will fix them in the future. Signed-off-by: Zhigang Gong Tested-by: Gaetan Nadon --- glamor/glamor_core.c | 13 ++++++++----- glamor/glamor_egl.c | 4 +++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 22065bc64..eb1a08d43 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -68,11 +68,14 @@ glamor_compile_glsl_prog(glamor_gl_dispatch * dispatch, GLenum type, dispatch->glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size); info = malloc(size); - - dispatch->glGetShaderInfoLog(prog, size, NULL, info); - ErrorF("Failed to compile %s: %s\n", - type == GL_FRAGMENT_SHADER ? "FS" : "VS", info); - ErrorF("Program source:\n%s", source); + if (info) { + dispatch->glGetShaderInfoLog(prog, size, NULL, info); + ErrorF("Failed to compile %s: %s\n", + type == GL_FRAGMENT_SHADER ? "FS" : "VS", info); + ErrorF("Program source:\n%s", source); + free(info); + } else + ErrorF("Failed to get shader compilation info.\n"); FatalError("GLSL compile failure\n"); } diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 50b764b6a..13b7f44ec 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -500,6 +500,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) glamor_identify(0); glamor_egl = calloc(sizeof(*glamor_egl), 1); + if (glamor_egl == NULL) + return FALSE; if (xf86GlamorEGLPrivateIndex == -1) xf86GlamorEGLPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); @@ -514,7 +516,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) } glamor_egl->display = eglGetDisplay(glamor_egl->gbm); #else - glamor_egl->display = eglGetDisplay((EGLNativeDisplayType)fd); + glamor_egl->display = eglGetDisplay((EGLNativeDisplayType)(intptr_t)fd); #endif glamor_egl->has_gem = glamor_egl_check_has_gem(fd); From 7cfd9cc23270c0246d584e167fe14bf5af4571df Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Thu, 5 Dec 2013 08:49:15 +0100 Subject: [PATCH 458/462] Add DRI3 support to glamor This implements some DRI3 helpers to help the DDXs using glamor to support DRI3. Signed-off-by: Axel Davy Reviewed-by: Zhigang Gong --- glamor/glamor.c | 76 ++++++++++++++- glamor/glamor.h | 68 ++++++++++++- glamor/glamor_egl.c | 225 +++++++++++++++++++++++++++++++++++++++++++ glamor/glamor_fbo.c | 34 ++++--- glamor/glamor_priv.h | 1 + 5 files changed, 391 insertions(+), 13 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index e8e68be53..93d3c5e72 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -209,7 +209,12 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap) Bool glamor_destroy_pixmap(PixmapPtr pixmap) { - glamor_destroy_textured_pixmap(pixmap); + glamor_screen_private + *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + if (glamor_priv->dri3_enabled) + glamor_egl_destroy_textured_pixmap(pixmap); + else + glamor_destroy_textured_pixmap(pixmap); return fbDestroyPixmap(pixmap); } @@ -552,3 +557,72 @@ glamor_fini(ScreenPtr screen) { /* Do nothing currently. */ } + +void glamor_enable_dri3(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_priv->dri3_enabled = TRUE; +} + +Bool glamor_is_dri3_support_enabled(ScreenPtr screen) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + return glamor_priv->dri3_enabled; +} + +int +glamor_dri3_fd_from_pixmap (ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, + CARD32 *size) +{ + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL || !glamor_priv->dri3_enabled) + return -1; + switch (pixmap_priv->type) + { + case GLAMOR_TEXTURE_DRM: + case GLAMOR_TEXTURE_ONLY: + glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0); + return glamor_egl_dri3_fd_name_from_tex(screen, + pixmap, + pixmap_priv->base.fbo->tex, + FALSE, + stride, + size); + default: break; + } + return -1; +} + +int +glamor_dri3_name_from_pixmap (PixmapPtr pixmap) +{ + glamor_pixmap_private *pixmap_priv; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(pixmap->drawable.pScreen); + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv == NULL || !glamor_priv->dri3_enabled) + return -1; + switch (pixmap_priv->type) + { + case GLAMOR_TEXTURE_DRM: + case GLAMOR_TEXTURE_ONLY: + glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0); + return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen, + pixmap, + pixmap_priv->base.fbo->tex, + TRUE, + NULL, + NULL); + default: break; + } + return -1; +} diff --git a/glamor/glamor.h b/glamor/glamor.h index 927892fd6..1bb48ed74 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -164,6 +164,71 @@ extern _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr bac extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back); +/* The DDX is not supposed to call these three functions */ +extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen); +extern _X_EXPORT unsigned int glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h); +extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr, unsigned int, Bool, CARD16*, CARD32*); + +/* @glamor_is_dri3_support_enabled: Returns if DRI3 support is enabled. + * + * @screen: Current screen pointer. + * + * To have DRI3 support enabled, glamor and glamor_egl need to be initialized, + * and glamor_egl_init_textured_pixmap need to be called. glamor also + * has to be compiled with gbm support. + * The EGL layer need to have the following extensions working: + * .EGL_KHR_gl_texture_2D_image + * .EGL_EXT_image_dma_buf_import + * If DRI3 support is not enabled, the following helpers will return an error. + * */ +extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen); + +/* @glamor_dri3_fd_from_pixmap: DRI3 helper to get a dma-buf fd from a pixmap. + * + * @screen: Current screen pointer. + * @pixmap: The pixmap from which we want the fd. + * @stride, @size: Pointers to fill the stride and size of the + * buffer associated to the fd. + * + * the pixmap and the buffer associated by the fd will share the same + * content. + * Returns the fd on success, -1 on error. + * */ +extern _X_EXPORT int glamor_dri3_fd_from_pixmap (ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, + CARD32 *size); + +/* @glamor_dri3_name_from_pixmap: helper to get an gem name from a pixmap. + * + * @pixmap: The pixmap from which we want the gem name. + * + * the pixmap and the buffer associated by the gem name will share the same + * content. This function can be used by the DDX to support DRI2, but needs + * glamor DRI3 support to be activated. + * Returns the name on success, -1 on error. + * */ +extern _X_EXPORT int glamor_dri3_name_from_pixmap (PixmapPtr pixmap); + +/* @glamor_egl_dri3_pixmap_from_fd: DRI3 helper to get a pixmap from a dma-buf fd. + * + * @screen: Current screen pointer. + * @fd: The dma-buf fd to import. + * @width: The width of the buffer. + * @height: The height of the buffer. + * @stride: The stride of the buffer. + * @depth: The depth of the buffer. + * @bpp: The number of bpp of the buffer. + * + * Returns a valid pixmap if the import succeeded, else NULL. + * */ +extern _X_EXPORT PixmapPtr glamor_egl_dri3_pixmap_from_fd (ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp); #ifdef GLAMOR_FOR_XORG @@ -243,9 +308,10 @@ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo); -extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); #endif +extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap); + extern _X_EXPORT int glamor_create_gc(GCPtr gc); extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 13b7f44ec..bf0db3a09 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -45,6 +45,7 @@ #ifdef GLAMOR_HAS_GBM #include +#include #endif #if GLAMOR_GLES2 @@ -95,6 +96,7 @@ struct glamor_egl_screen_private { void *glamor_context; void *current_context; int gl_context_depth; + int dri3_capable; PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr; PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr; @@ -218,6 +220,47 @@ glamor_create_texture_from_image(struct glamor_egl_screen_private return TRUE; } +unsigned int +glamor_egl_create_argb8888_based_texture(ScreenPtr screen, + int w, + int h) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl; + EGLImageKHR image; + GLuint texture; +#ifdef GLAMOR_HAS_DRI3_SUPPORT + struct gbm_bo *bo; + EGLNativePixmapType native_pixmap; + glamor_egl = glamor_egl_get_screen_private(scrn); + bo = gbm_bo_create (glamor_egl->gbm, w, h, GBM_FORMAT_ARGB8888, + GBM_BO_USE_RENDERING | + GBM_BO_USE_SCANOUT); + if (!bo) + return 0; + + /* If the following assignment raises an error or a warning + * then that means EGLNativePixmapType is not struct gbm_bo * + * on your platform: This code won't work and you should not + * compile with dri3 support enabled */ + native_pixmap = bo; + + image = glamor_egl->egl_create_image_khr(glamor_egl->display, + EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, + native_pixmap, NULL); + gbm_bo_destroy(bo); + if (image == EGL_NO_IMAGE_KHR) + return 0; + glamor_create_texture_from_image(glamor_egl, image, &texture); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, image); + + return texture; +#else + return 0; /* this path should never happen */ +#endif +} + Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) { @@ -349,6 +392,178 @@ done: return ret; } +#ifdef GLAMOR_HAS_DRI3_SUPPORT +int glamor_get_fd_from_bo (int gbm_fd, struct gbm_bo *bo, int *fd); +void glamor_get_name_from_bo (int gbm_fd, struct gbm_bo *bo, int *name); +int +glamor_get_fd_from_bo (int gbm_fd, struct gbm_bo *bo, int *fd) +{ + union gbm_bo_handle handle; + struct drm_prime_handle args; + + handle = gbm_bo_get_handle(bo); + args.handle = handle.u32; + args.flags = DRM_CLOEXEC; + if (ioctl (gbm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args)) + return FALSE; + *fd = args.fd; + return TRUE; +} + +void +glamor_get_name_from_bo (int gbm_fd, struct gbm_bo *bo, int *name) +{ + union gbm_bo_handle handle; + + handle = gbm_bo_get_handle(bo); + if (!glamor_get_flink_name(gbm_fd, handle.u32, name)) + *name = -1; +} +#endif + +int glamor_egl_dri3_fd_name_from_tex (ScreenPtr screen, + PixmapPtr pixmap, + unsigned int tex, + Bool want_name, + CARD16 *stride, + CARD32 *size) +{ +#ifdef GLAMOR_HAS_DRI3_SUPPORT + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl; + EGLImageKHR image; + struct gbm_bo* bo; + int fd = -1; + + EGLint attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_GL_TEXTURE_LEVEL_KHR, 0, + EGL_NONE + }; + + glamor_egl = glamor_egl_get_screen_private(scrn); + + glamor_egl_make_current(screen); + + image = dixLookupPrivate(&pixmap->devPrivates, + glamor_egl_pixmap_private_key); + + if (image == EGL_NO_IMAGE_KHR || image == NULL) + { + image = glamor_egl->egl_create_image_khr(glamor_egl->display, + glamor_egl->context, + EGL_GL_TEXTURE_2D_KHR, + tex, attribs); + if (image == EGL_NO_IMAGE_KHR) + goto failure; + + dixSetPrivate(&pixmap->devPrivates, + glamor_egl_pixmap_private_key, + image); + glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); + } + + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); + if (!bo) + goto failure; + + pixmap->devKind = gbm_bo_get_stride(bo); + + if (want_name) + { + if (glamor_egl->has_gem) + glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); + } + else + { + if (glamor_get_fd_from_bo(glamor_egl->fd, bo, &fd)) + { + *stride = pixmap->devKind; + *size = pixmap->devKind * gbm_bo_get_height(bo); + } + } + + gbm_bo_destroy(bo); +failure: + glamor_egl_restore_context(screen); + return fd; +#else + return -1; +#endif +} + +PixmapPtr glamor_egl_dri3_pixmap_from_fd (ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp) +{ +#ifdef GLAMOR_HAS_DRI3_SUPPORT + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl; + struct gbm_bo* bo; + EGLImageKHR image; + PixmapPtr pixmap; + Bool ret = FALSE; + EGLint attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, + EGL_DMA_BUF_PLANE0_FD_EXT, 0, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, + EGL_NONE + }; + + glamor_egl = glamor_egl_get_screen_private(scrn); + + if (!glamor_egl->dri3_capable) + return NULL; + + if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0) + return NULL; + + attribs[1] = width; + attribs[3] = height; + attribs[7] = fd; + attribs[11] = stride; + image = glamor_egl->egl_create_image_khr(glamor_egl->display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, attribs); + + if (image == EGL_NO_IMAGE_KHR) + return NULL; + + /* EGL_EXT_image_dma_buf_import can impose restrictions on the + * usage of the image. Use gbm_bo to bypass the limitations. */ + + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, image); + + if (!bo) + return NULL; + + pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); + screen->ModifyPixmapHeader (pixmap, width, height, 0, 0, stride, NULL); + + ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); + gbm_bo_destroy(bo); + + if (ret) + return pixmap; + else + { + screen->DestroyPixmap(pixmap); + return NULL; + } +#else + return NULL; +#endif +} + static void _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) { @@ -558,6 +773,11 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) GLAMOR_CHECK_EGL_EXTENSIONS(KHR_surfaceless_context, KHR_surfaceless_opengl); #endif +#ifdef GLAMOR_HAS_DRI3_SUPPORT + if (glamor_egl_has_extension(glamor_egl, "EGL_KHR_gl_texture_2D_image") && + glamor_egl_has_extension(glamor_egl, "EGL_EXT_image_dma_buf_import") ) + glamor_egl->dri3_capable = TRUE; +#endif glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); @@ -609,6 +829,9 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) Bool glamor_egl_init_textured_pixmap(ScreenPtr screen) { + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); if (!dixRegisterPrivateKey (glamor_egl_pixmap_private_key, PRIVATE_PIXMAP, 0)) { LogMessage(X_WARNING, @@ -616,6 +839,8 @@ glamor_egl_init_textured_pixmap(ScreenPtr screen) screen->myNum); return FALSE; } + if (glamor_egl->dri3_capable) + glamor_enable_dri3(screen); return TRUE; } diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 4838a277f..d1b087ebe 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -328,18 +328,30 @@ _glamor_create_tex(glamor_screen_private *glamor_priv, int w, int h, GLenum format) { glamor_gl_dispatch *dispatch; - unsigned int tex; + unsigned int tex = 0; - dispatch = glamor_get_dispatch(glamor_priv); - dispatch->glGenTextures(1, &tex); - dispatch->glBindTexture(GL_TEXTURE_2D, tex); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, - GL_UNSIGNED_BYTE, NULL); - glamor_put_dispatch(glamor_priv); + /* With dri3, we want to allocate ARGB8888 pixmaps only. + * Depending on the implementation, GL_RGBA might not + * give us ARGB8888. We ask glamor_egl to use get + * an ARGB8888 based texture for us. */ + if (glamor_priv->dri3_enabled && format == GL_RGBA) + { + tex = glamor_egl_create_argb8888_based_texture(glamor_priv->screen, + w, h); + } + if (!tex) + { + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glGenTextures(1, &tex); + dispatch->glBindTexture(GL_TEXTURE_2D, tex); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, + format, GL_UNSIGNED_BYTE, NULL); + glamor_put_dispatch(glamor_priv); + } return tex; } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b6a1075ad..7b8f762c9 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -305,6 +305,7 @@ typedef struct glamor_screen_private { int state; unsigned int render_idle_cnt; ScreenPtr screen; + int dri3_enabled; /* xv */ GLint xv_prog; From 752a79562eb13f59fa54b4181d65367c8488c0a5 Mon Sep 17 00:00:00 2001 From: Gaetan Nadon Date: Sun, 8 Dec 2013 16:43:08 -0500 Subject: [PATCH 459/462] Fix glamor_egl->egl_create_image_khr makes pointer from integer This is a warning, but a real problem can occur on some system. Reported-by: Fabio Pedretti Reviewed-by: Axel Davy Signed-off-by: Gaetan Nadon Reviewed-by: Zhigang Gong --- glamor/glamor_egl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index bf0db3a09..ff4c0bdd9 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -453,7 +453,7 @@ int glamor_egl_dri3_fd_name_from_tex (ScreenPtr screen, image = glamor_egl->egl_create_image_khr(glamor_egl->display, glamor_egl->context, EGL_GL_TEXTURE_2D_KHR, - tex, attribs); + (EGLClientBuffer)(uintptr_t)tex, attribs); if (image == EGL_NO_IMAGE_KHR) goto failure; From b8055bd1f6c9dea0fe8f7a786d2a1522f5f32129 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 13 Dec 2013 11:33:46 +1000 Subject: [PATCH 460/462] glamor: fix leak in xv code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This loop needed to go one higher, not sure if this fixes the leak MrCooper was seeing on irc, but it fixes a leak. Signed-off-by: Dave Airlie Reviewed-by: Michel Dänzer Reviewed-by: Zhigang Gong --- glamor/glamor_xv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c index 8f12c1f1e..a89b4cd3f 100644 --- a/glamor/glamor_xv.c +++ b/glamor/glamor_xv.c @@ -490,7 +490,7 @@ static int glamor_xv_put_image(ScrnInfoPtr pScrn, if (!port_priv->src_pix[0] || (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) { int i; - for (i = 0; i < 2; i++) + for (i = 0; i < 3; i++) if (port_priv->src_pix[i]) glamor_destroy_pixmap(port_priv->src_pix[i]); From 08c23ff8aefe80f2940ecb90adda27156084f57c Mon Sep 17 00:00:00 2001 From: Gaetan Nadon Date: Tue, 10 Dec 2013 11:13:31 -0500 Subject: [PATCH 461/462] Make: remove cruft copied over from the X server makefiles In toplevel makefile: nostdinc: only xserver, no other X modules aclocaldir: no local macros to install xkb_path: xserver only "Gross hack": xserver only In src/makefile: SOLARIS_ASM_CFLAGS; server only XORG_INCS: undefined variable DIX_CFLAGS: undefined variable Signed-off-by: Gaetan Nadon Reviewed-by: Zhigang Gong --- glamor/Makefile.am | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 50cfe97ea..79ea95919 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -1,19 +1,12 @@ lib_LTLIBRARIES = libglamor.la -# Override these since glamor doesn't need them and the needed files aren't -# built (in hw/xfree86/os-support/solaris) until after glamor is built -SOLARIS_ASM_CFLAGS="" - if GLAMOR_GLES2 libglamor_la_LIBADD = $(GLESV2_LIBS) else libglamor_la_LIBADD = $(GL_LIBS) endif -AM_CPPFLAGS = \ - $(XORG_INCS) - -AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) $(DIX_CFLAGS) $(LIBDRM_CFLAGS) +AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) $(LIBDRM_CFLAGS) libglamor_la_LDFLAGS = -version-info 0:0:0 From 4dd62d7807b47efbc9065ae8f17f73e1ec6e9d26 Mon Sep 17 00:00:00 2001 From: Gaetan Nadon Date: Tue, 10 Dec 2013 11:13:32 -0500 Subject: [PATCH 462/462] libglamoregl: remove -I$(top_srcdir)/src Automake always provide -I. It is at the beginning of the list of compiler options. Not needed either to find glamor_egl.c source. Signed-off-by: Gaetan Nadon Reviewed-by: Zhigang Gong --- glamor/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 79ea95919..2fd521f11 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -59,11 +59,10 @@ module_LTLIBRARIES = $(LIBGLAMOREGL) libglamoregl_la_DEPENDENCIES = libglamor.la libglamoregl_la_LDFLAGS = -avoid-version -module libglamoregl_la_LIBADD = $(EGL_LIBS) $(GLX_SYS_LIBS) $(GBM_LIBS) libglamor.la -libglamoregl_la_SOURCES = glamor_eglmodule.c $(top_srcdir)/src/glamor_egl.c +libglamoregl_la_SOURCES = glamor_eglmodule.c glamor_egl.c libglamoregl_la_CFLAGS = \ $(AM_CFLAGS) \ $(GLX_DEFINES) \ - -I$(top_srcdir)/src \ $(LIBDRM_CFLAGS) \ $(EGL_CFLAGS) \ $(GBM_CFLAGS)