From 5cfbe97cd797d8f78ece208bb5114704b83d8aab Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 13 Jan 2012 16:54:57 +0100 Subject: libxtrans libXdmcp libxcb mesa xserver git update 13 jan 2012 --- X11/xtrans/doc/xtrans.xml | 65 +- libXdmcp/doc/xdmcp.xml | 570 +- libxcb/NEWS | 891 ++-- libxcb/configure.ac | 4 +- libxcb/src/xcb.h | 24 +- libxcb/src/xcb_auth.c | 9 +- libxcb/src/xcb_conn.c | 851 +-- libxcb/src/xcb_in.c | 14 +- libxcb/src/xcb_out.c | 750 +-- libxcb/src/xcb_util.c | 19 +- libxcb/src/xcbint.h | 7 +- libxcb/xcb-proto/NEWS | 34 +- libxcb/xcb-proto/configure.ac | 2 +- libxcb/xcb-proto/src/xkb.xml | 5549 ++++++++++---------- libxcb/xcb-proto/src/xproto.xml | 7 +- mesalib/Makefile | 2 + mesalib/configs/linux-dri | 5 +- mesalib/configure.ac | 5 +- mesalib/docs/GL3.txt | 88 +- mesalib/src/gallium/auxiliary/util/u_math.h | 5 + mesalib/src/glsl/glsl_types.cpp | 29 + mesalib/src/glsl/glsl_types.h | 6 + mesalib/src/glsl/link_uniforms.cpp | 60 +- mesalib/src/glsl/linker.cpp | 143 +- mesalib/src/mesa/drivers/common/meta.c | 7 +- mesalib/src/mesa/main/api_validate.c | 2 +- mesalib/src/mesa/main/arrayobj.c | 2 +- mesalib/src/mesa/main/bitset.h | 2 +- mesalib/src/mesa/main/buffers.c | 25 +- mesalib/src/mesa/main/clear.c | 15 +- mesalib/src/mesa/main/drawpix.c | 6 + mesalib/src/mesa/main/fbobject.c | 50 +- mesalib/src/mesa/main/fbobject.h | 22 + mesalib/src/mesa/main/ff_fragment_shader.cpp | 42 +- mesalib/src/mesa/main/ffvertex_prog.c | 2 +- mesalib/src/mesa/main/framebuffer.c | 9 +- mesalib/src/mesa/main/hash.c | 20 + mesalib/src/mesa/main/hash.h | 3 + mesalib/src/mesa/main/imports.c | 15 +- mesalib/src/mesa/main/imports.h | 25 +- mesalib/src/mesa/main/mipmap.c | 2 +- mesalib/src/mesa/main/mtypes.h | 20 +- mesalib/src/mesa/main/readpix.c | 5 + mesalib/src/mesa/main/renderbuffer.c | 2 +- mesalib/src/mesa/main/shaderapi.c | 95 +- mesalib/src/mesa/main/state.c | 12 +- mesalib/src/mesa/main/teximage.c | 20 +- mesalib/src/mesa/main/texobj.c | 10 +- mesalib/src/mesa/main/texstore.c | 6 +- mesalib/src/mesa/main/uniform_query.cpp | 58 +- mesalib/src/mesa/main/uniforms.c | 7 +- mesalib/src/mesa/main/uniforms.h | 6 +- mesalib/src/mesa/main/version.h | 11 - mesalib/src/mesa/program/ir_to_mesa.cpp | 33 +- mesalib/src/mesa/program/prog_print.c | 4 +- mesalib/src/mesa/state_tracker/st_atom_texture.c | 35 +- mesalib/src/mesa/state_tracker/st_draw.c | 3 +- mesalib/src/mesa/state_tracker/st_draw_feedback.c | 2 +- mesalib/src/mesa/state_tracker/st_extensions.c | 31 +- mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 34 +- mesalib/src/mesa/state_tracker/st_manager.c | 20 +- mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c | 7 +- mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.h | 5 +- mesalib/src/mesa/swrast/s_aalinetemp.h | 484 +- mesalib/src/mesa/swrast/s_context.c | 2 +- mesalib/src/mesa/swrast/s_span.c | 6 +- mesalib/src/mesa/swrast/s_texture.c | 4 +- mesalib/src/mesa/tnl/t_draw.c | 2 +- mesalib/src/mesa/vbo/vbo.h | 6 +- mesalib/src/mesa/vbo/vbo_exec_array.c | 53 +- xorg-server/Xext/xf86bigfont.c | 4 +- xorg-server/dix/dispatch.c | 12 +- xorg-server/dix/events.c | 5 +- xorg-server/hw/kdrive/ephyr/ephyrdriext.c | 4 +- xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c | 2 +- xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c | 6 +- xorg-server/hw/xfree86/dri/xf86dri.c | 4 +- xorg-server/hw/xfree86/dri2/dri2ext.c | 2 +- xorg-server/hw/xfree86/man/xorg.conf.man | 8 +- xorg-server/hw/xquartz/applewm.c | 4 +- xorg-server/hw/xquartz/xpr/appledri.c | 4 +- xorg-server/hw/xwin/winwindowswm.c | 4 +- xorg-server/include/dixstruct.h | 30 +- xorg-server/include/misc.h | 3 +- xorg-server/include/os.h | 2 + xorg-server/include/windowstr.h | 4 +- xorg-server/os/access.c | 9 +- xorg-server/os/backtrace.c | 8 +- xorg-server/os/connection.c | 14 +- xorg-server/os/io.c | 19 +- xorg-server/os/osdep.h | 19 +- xorg-server/render/animcur.c | 837 +-- 92 files changed, 5912 insertions(+), 5463 deletions(-) diff --git a/X11/xtrans/doc/xtrans.xml b/X11/xtrans/doc/xtrans.xml index 82e95a408..12dbe3c7f 100644 --- a/X11/xtrans/doc/xtrans.xml +++ b/X11/xtrans/doc/xtrans.xml @@ -956,13 +956,14 @@ In X11R7 modular releases, these flags are set when running XTRANS_CONNECTION_FLAGS macro from xtrans.m4. - - - - - + + + + + + - + #define configure flag Description @@ -1021,15 +1022,15 @@ In X11R7 modular releases, these flags are set when running Transport Specific Definitions - + - - - - + + + + - Protocol Family + Protocol Family Address Component @@ -1040,34 +1041,34 @@ In X11R7 modular releases, these flags are set when running - Internet - inet inet6 tcp udp - name of an internet addressable host - string containing the name of a service or a valid port number. Example: "xserver0", "7100" + Internet + inet inet6 tcp udp + name of an internet addressable host + string containing the name of a service or a valid port number. Example: "xserver0", "7100" - DECnet - decnet - name of a DECnet addressable host - string containing the complete name of the object. Example: "X$X0" + DECnet + decnet + name of a DECnet addressable host + string containing the complete name of the object. Example: "X$X0" - NETware - ipx - name of a NETware addressable host - Not sure of the specifics yet. + NETware + ipx + name of a NETware addressable host + Not sure of the specifics yet. - OSI - osi - name of an OSI adressable host. - Not sure of the specifics yet. + OSI + osi + name of an OSI adressable host. + Not sure of the specifics yet. - Local - local pts named sco isc - (ignored) - String containing the port name, ie "xserver0", "fontserver0". + Local + local pts named sco isc + (ignored) + String containing the port name, ie "xserver0", "fontserver0". diff --git a/libXdmcp/doc/xdmcp.xml b/libXdmcp/doc/xdmcp.xml index 817838e58..0f0ab3f2b 100644 --- a/libXdmcp/doc/xdmcp.xml +++ b/libXdmcp/doc/xdmcp.xml @@ -265,35 +265,36 @@ restriction will not substantially hamper the efficiency of any implementation. Also, no padding of any sort will occur within the packets. - - - - - + + + + + + - + Type Name Length (Bytes) Description - + CARD8 1 A single byte unsigned integer - + CARD16 2 Two byte unsigned integer - + CARD32 4 Four byte unsigned integer - + ARRAY8 n+2 @@ -302,7 +303,7 @@ a collection of CARD8. The value of the CARD16 field (n) specifies the number of CARD8 values to follow - + ARRAY16 2*m+1 @@ -310,7 +311,7 @@ This is a CARD8 (m) which specifies the number of CARD16 values to follow - + ARRAY32 4*l+1 @@ -318,7 +319,7 @@ This is a CARD8 (l) which specifies the number of CARD32 values to follow - + ARRAYofARRAY8 ? @@ -340,35 +341,36 @@ number of ARRAY8 values to follow. All XDMCP packets have the following information: - - - - - + + + + + + - + Length (Bytes) Field Type Description - + 2 CARD16 version number - + 2 CARD16 opcode packet header - + 2 CARD16 n = length of remaining data in bytes - + n ??? packet-specific data @@ -480,49 +482,49 @@ header in the order described without padding, and the length field is computed accordingly. - + - - - - - - - - - - + + + + + + + + + + - + Query - + BroadcastQuery - + IndirectQuery - + Display -> Manager - + Additional Fields: - + Authentication Names: ARRAYofARRAY8 - + @@ -533,12 +535,12 @@ manager will choose one of these and return it in the - + - Semantics + Semantics - + @@ -588,7 +590,7 @@ Each packet type has slightly different semantics: - + @@ -632,13 +634,13 @@ is not forwarded. - + Valid Responses: - + @@ -646,18 +648,18 @@ is not forwarded. Unwilling - + Problems/Solutions: - + Problem: - + @@ -666,7 +668,7 @@ is not forwarded. Indication: - + @@ -680,13 +682,13 @@ was sent, else failure to receive Willing. - + Solution: - + @@ -695,14 +697,14 @@ was sent, else failure to receive Repeatedly send the packet while waiting for user to choose a manager. - + Timeout/Retransmission policy: - + @@ -714,26 +716,26 @@ should reset the timeout when user-input is detected. In this way, the display will wakeup when touched by the user. - + ForwardQuery - + Primary Manager -> Secondary Manager Additional Fields: - + Client Address: ARRAY8 - + @@ -741,14 +743,14 @@ display will wakeup when touched by the user. Specifies the network address of the client display. - + Client Port: ARRAY8 - + @@ -756,14 +758,14 @@ Specifies the network address of the client display. Specifies an identification of the client task on the client display. - + Authentication Names: ARRAYofARRAY8 - + @@ -774,13 +776,13 @@ in the packet. - + Semantics: - + @@ -812,27 +814,27 @@ packet. - + Valid Responses: - + Willing - + Problems/Solutions: - + @@ -840,13 +842,13 @@ Identical to BroadcastQuery - + Timeout/Retransmission policy: - + @@ -855,13 +857,13 @@ retransmitted. - + Willing - + @@ -873,7 +875,7 @@ Additional Fields: - + @@ -881,7 +883,7 @@ Additional Fields: - + @@ -909,7 +911,7 @@ of authentication. - + @@ -917,7 +919,7 @@ of authentication. - + @@ -927,7 +929,7 @@ The protocol specifies no interpretation of the data in this field. - + @@ -935,7 +937,7 @@ The protocol specifies no interpretation of the data in this field. - + @@ -947,14 +949,14 @@ protocol specifies no interpretation of the data in this field. - + Semantics: - + @@ -972,14 +974,14 @@ connections already). - + Problems/Solutions: - + @@ -987,7 +989,7 @@ Problem: - + @@ -1002,7 +1004,7 @@ Indication: - + @@ -1017,7 +1019,7 @@ was sent, else failure to receive - + @@ -1026,7 +1028,7 @@ Solution: - + @@ -1038,14 +1040,14 @@ The display should continue to send the query until a response is received. - + Timeout/Retransmission policy: - + @@ -1054,13 +1056,13 @@ never be retransmitted. - + Unwilling - + @@ -1072,7 +1074,7 @@ Additional Fields: - + @@ -1084,14 +1086,14 @@ for the refusal of service. - + Semantics: - + @@ -1109,14 +1111,14 @@ particular displays or that handle a limited number of displays at once. - + Problems/Solutions: - + @@ -1124,7 +1126,7 @@ Problem: - + @@ -1139,7 +1141,7 @@ Indication: - + @@ -1150,7 +1152,7 @@ Display fails to receive - + @@ -1159,7 +1161,7 @@ Solution: - + @@ -1171,14 +1173,14 @@ messages until a response is received. - + Timeout/Retransmission policy: - + @@ -1186,13 +1188,13 @@ Like all packets sent from the manager to the display, this packet should never be retransmitted. - + Request - + @@ -1204,7 +1206,7 @@ Additional Fields: - + @@ -1212,7 +1214,7 @@ Additional Fields: - + @@ -1223,7 +1225,7 @@ This value will be zero for most autonomous displays. - + @@ -1231,7 +1233,7 @@ This value will be zero for most autonomous displays. - + @@ -1242,7 +1244,7 @@ corresponds to an X-protocol host family type. - + @@ -1250,7 +1252,7 @@ corresponds to an X-protocol host family type. - + @@ -1260,7 +1262,7 @@ this array indicates the network address of the display device. - + @@ -1273,7 +1275,7 @@ this array indicates the network address of the display device. - + @@ -1285,7 +1287,7 @@ and use to authenticate itself. - + @@ -1293,7 +1295,7 @@ and use to authenticate itself. - + @@ -1304,7 +1306,7 @@ authorization. - + @@ -1312,7 +1314,7 @@ authorization. - + @@ -1323,14 +1325,14 @@ Manufacturer Display ID Format. - + Semantics: - + @@ -1348,14 +1350,14 @@ packet. - + Valid Responses: - + @@ -1364,14 +1366,14 @@ Valid Responses: - + Problems/Solutions: - + @@ -1379,7 +1381,7 @@ Problem: - + @@ -1388,7 +1390,7 @@ Request not received by manager. - + @@ -1397,7 +1399,7 @@ Indication: - + @@ -1407,7 +1409,7 @@ Display timeout waiting for response. - + @@ -1416,7 +1418,7 @@ Solution: - + @@ -1429,7 +1431,7 @@ message. - + @@ -1438,7 +1440,7 @@ Problem: - + @@ -1448,7 +1450,7 @@ Message received out of order by manager. - + @@ -1457,7 +1459,7 @@ Indication: - + @@ -1467,7 +1469,7 @@ None. - + @@ -1476,7 +1478,7 @@ Solution: - + @@ -1496,14 +1498,14 @@ will be discarded by the display. - + Timeout/Retransmission policy: - + @@ -1512,13 +1514,13 @@ After no more than 126 seconds, give up and report an error to the user. - + Accept - + @@ -1530,7 +1532,7 @@ Additional Fields: - + @@ -1538,7 +1540,7 @@ Additional Fields: - + @@ -1547,7 +1549,7 @@ Identifies the session that can be started by the manager. - + @@ -1560,7 +1562,7 @@ Identifies the session that can be started by the manager. - + @@ -1571,7 +1573,7 @@ should terminate the protocol at this point and display an error to the user. - + @@ -1584,7 +1586,7 @@ should terminate the protocol at this point and display an error to the user. - + @@ -1599,14 +1601,14 @@ packet is received. - + Semantics: - + @@ -1634,14 +1636,14 @@ message. - + Problems/Solutions: - + @@ -1649,7 +1651,7 @@ Problem: - + @@ -1661,7 +1663,7 @@ not received by display. - + @@ -1670,7 +1672,7 @@ Indication: - + @@ -1681,7 +1683,7 @@ Display timeout waiting for response to - + @@ -1690,7 +1692,7 @@ Solution: - + @@ -1702,7 +1704,7 @@ message. - + @@ -1710,7 +1712,7 @@ Problem: - + @@ -1719,7 +1721,7 @@ Message received out of order by display. - + @@ -1728,7 +1730,7 @@ Indication: - + @@ -1742,7 +1744,7 @@ has been sent. - + @@ -1751,7 +1753,7 @@ Solution: - + @@ -1765,14 +1767,14 @@ message. - + Timeout/Retransmission policy: - + @@ -1781,13 +1783,13 @@ never be retransmitted. - + Decline - + @@ -1799,7 +1801,7 @@ Additional Fields: - + @@ -1807,7 +1809,7 @@ Additional Fields: - + @@ -1817,7 +1819,7 @@ service. - + @@ -1832,7 +1834,7 @@ ARRAY8 - + @@ -1843,14 +1845,14 @@ should terminate the protocol at this point and display an error to the user. - + Semantics: - + @@ -1866,14 +1868,14 @@ to a previous query. - + Problems/Solutions: - + @@ -1882,14 +1884,14 @@ Same as for - + Timeout/Retransmission policy: - + @@ -1898,13 +1900,13 @@ be retransmitted. - + Manage - + @@ -1916,7 +1918,7 @@ Additional Fields: - + @@ -1924,7 +1926,7 @@ Additional Fields: - + @@ -1935,7 +1937,7 @@ packet. - + @@ -1943,7 +1945,7 @@ packet. - + @@ -1954,7 +1956,7 @@ packet. - + @@ -1962,7 +1964,7 @@ packet. - + @@ -1974,14 +1976,14 @@ which discusses the format of this field. - + Semantics: - + @@ -2006,14 +2008,14 @@ packet). - + Valid Responses: - + @@ -2023,14 +2025,14 @@ X connection with correct auth info, - + Problems/Solutions: - + @@ -2038,7 +2040,7 @@ Problem: - + @@ -2048,7 +2050,7 @@ not received by manager. - + @@ -2057,7 +2059,7 @@ Indication: - + @@ -2067,7 +2069,7 @@ Display timeout waiting for response. - + @@ -2076,7 +2078,7 @@ Solution: - + @@ -2089,7 +2091,7 @@ message. - + @@ -2097,7 +2099,7 @@ Problem: - + @@ -2107,7 +2109,7 @@ received out of order by manager. - + @@ -2116,7 +2118,7 @@ Indication: - + @@ -2126,7 +2128,7 @@ Session already in progress with matching Session ID. - + @@ -2135,7 +2137,7 @@ Solution: - + @@ -2146,7 +2148,7 @@ packet ignored. - + @@ -2155,7 +2157,7 @@ Indication: - + @@ -2165,7 +2167,7 @@ Session ID does not match next Session ID. - + @@ -2174,7 +2176,7 @@ Solution: - + @@ -2186,7 +2188,7 @@ message is sent. - + @@ -2194,7 +2196,7 @@ Problem: - + @@ -2203,7 +2205,7 @@ Display cannot be opened on selected stream. - + @@ -2212,7 +2214,7 @@ Indication: - + @@ -2222,7 +2224,7 @@ Display connection setup fails. - + @@ -2231,7 +2233,7 @@ Solution: - + @@ -2242,7 +2244,7 @@ message is sent including a human readable reason. - + @@ -2250,7 +2252,7 @@ Problem: - + @@ -2260,7 +2262,7 @@ because of a timeout occuring in the display. - + @@ -2269,7 +2271,7 @@ Indication: - + @@ -2281,7 +2283,7 @@ attempting to connect to the display. - + @@ -2290,7 +2292,7 @@ Solution: - + @@ -2307,14 +2309,14 @@ packet is necessary. - + Timeout/Retransmission policy: - + @@ -2323,13 +2325,13 @@ than 126 seconds, give up and report an error to the user. - + Refuse - + @@ -2341,7 +2343,7 @@ Additional Fields: - + @@ -2349,7 +2351,7 @@ Additional Fields: - + @@ -2361,14 +2363,14 @@ packet. - + Semantics: - + @@ -2385,14 +2387,14 @@ packet. - + Problems/Solutions: - + @@ -2400,7 +2402,7 @@ Problem: - + @@ -2409,7 +2411,7 @@ Error message is lost. - + @@ -2418,7 +2420,7 @@ Indication: - + @@ -2432,7 +2434,7 @@ or - + @@ -2441,7 +2443,7 @@ Solution: - + @@ -2455,14 +2457,14 @@ message. - + Timeout/Retransmission policy: - + @@ -2471,13 +2473,13 @@ retransmitted. - + Failed - + @@ -2489,7 +2491,7 @@ Additional Fields: - + @@ -2497,7 +2499,7 @@ Additional Fields: - + @@ -2508,7 +2510,7 @@ packet. - + @@ -2516,7 +2518,7 @@ packet. - + @@ -2526,14 +2528,14 @@ Is a human readable string indicating the reason for failure. - + Semantics: - + @@ -2546,14 +2548,14 @@ packet. - + Problems/Solutions - + @@ -2562,13 +2564,13 @@ Same as for - + KeepAlive - + @@ -2580,7 +2582,7 @@ Additional Fields: - + @@ -2588,7 +2590,7 @@ Additional Fields: - + @@ -2597,7 +2599,7 @@ Set to the display index for the display host. - + @@ -2605,7 +2607,7 @@ Set to the display index for the display host. - + @@ -2616,14 +2618,14 @@ packet during the negotiation for the current session. - + Sematics: - + @@ -2656,14 +2658,14 @@ most recent packet. - + Valid Responses: - + @@ -2671,14 +2673,14 @@ Valid Responses: - + Problems/Solutions: - + @@ -2686,7 +2688,7 @@ Problem: - + @@ -2696,7 +2698,7 @@ Manager does not receive the packet or display does not receive the response. - + @@ -2705,7 +2707,7 @@ Indication: - + @@ -2717,7 +2719,7 @@ packet is returned. - + @@ -2726,7 +2728,7 @@ Solution: - + @@ -2737,13 +2739,13 @@ assume the host is not up after no less than 30 seconds. - + Alive - + @@ -2755,7 +2757,7 @@ Additional Fields: - + @@ -2763,7 +2765,7 @@ Additional Fields: - + @@ -2775,7 +2777,7 @@ is active. - + @@ -2783,7 +2785,7 @@ is active. - + @@ -2794,14 +2796,14 @@ When no session is active this field should be zero. - + Semantics: - + @@ -3386,66 +3388,66 @@ multicast address. The version number in all packets will be 1. Packet opcodes are 16-bit integers. - - - - + + + + - + Packet Name Encoding - + BroadcastQuery 1 - + Query 2 - + IndirectQuery 3 - + ForwardQuery 4 - + Willing 5 - + Unwilling 6 - + Request 7 - + Accept 8 - + Decline 9 - + Manage 10 - + Refuse 11 - + Failed 12 - + KeepAlive 13 @@ -3455,7 +3457,7 @@ A previous version of this document incorrectly reversed the opcodes of - + Alive 14 diff --git a/libxcb/NEWS b/libxcb/NEWS index eaa31e885..bb4b47d68 100644 --- a/libxcb/NEWS +++ b/libxcb/NEWS @@ -1,423 +1,468 @@ -Release 1.7 (2010-08-13) -======================== -- Always wake up readers after writing -- Get rid of PATH_MAX and MAXPATHLEN -- Add ~ operator support in code generator -- xcb_open: Improve protocol/host parsing -- xcb_connect_to_display_with_auth_info: Fix memory leak -- Report which extensions are being built - -Release 1.6 (2010-04-09) -======================== -- darwin: xnu doesn't support poll on ttys on the master side -- Fix descriptor leak on memory error path -- Support xcb_discard_reply -- Open the X11 socket with close-on-exec flag -- Fix authentication on hpux and Hurd - -Release 1.5 (2009-12-03) -======================== -- setsockopt(SO_KEEPALIVE) on TCP display connections -- Add DRI2 support -- Fix check dependency -- Cygwin build fix: Add -no-undefined to libtool flags - -Release 1.4 (2009-07-15) -======================== -* Add majorCode, minorCode and resourceID fields to X generic error -* Fix precedence bug: wrong length for big-requests preceded by sync -* Fix libxcb-randr version info - -Release 1.3 (2009-05-29) -======================== -* Copy full IPv4 mapping (Bug #20665) -* Fix XID allocation -* Use poll() instead of select() when available -* Fix local socket connection on Hurd -* Fix XDM-AUTHORIZATION-1 -* Disable Nagle on TCP socket - -Release 1.2 (2009-02-17) -======================== -* Stop packaging auto-generated C files into tarball. - -Release 1.1.93 (2008-12-11) -=========================== -Enhancements: -* Apple: Enable support for launchd DISPLAY socket -* Treat XIDs the same as other cardinal values. - -Release 1.1.92 (2008-11-01) -=========================== -Enhancements: -* Added small fix to support trailing fixed fields; also warning for non-pad fixed fields -* Fixed overly aggressive warning about fixed field following variable -* Added generation of extern "C" for compatibility with C++ -* Remove libxcb-xlib and xcbxlib.h. -* Inline _xcb_lock_io, _xcb_unlock_io, and _xcb_wait_io. -* Track 64-bit sequence numbers internally. -* Use sequence number ranges in pending replies -* Remove duplicate XCB_EXTENSION calls for Composite extension -* Factorize m4 macros and add one to set X extensions -* Allow compile-time setting for XCB queue buffer size -* Support handing off socket write permission to external code. -* Add support for the abstract socket namespace under Linux - -Bug fixes: -* Fix tiny memory leak in read_packet -* Fix some fd leaks in _xcb_open_*() - -Release 1.1 (2007-11-04) -======================== - -This release requires xcb-proto 1.1, due to the addition of the -extension-multiword attribute to the XML schema. - -This release contains several important bug fixes, summarized below. It -also contains a patch much like Novell's libxcb-sloppy-lock.diff. -Rationale from the commit message follows. The patch and this rationale -were authored by Jamey Sharp , with agreement from -Josh Triplett . - - I strongly opposed proposals like this one for a long time. - Originally I had a very good reason: libX11, when compiled to use - XCB, would crash soon after a locking correctness violation, so it - was better to have an informative assert failure than a mystifying - crash soon after. - - It took some time for me to realize that I'd changed the libX11 - implementation (for unrelated reasons) so that it could survive most - invalid locking situations, as long as it wasn't actually being used - from multiple threads concurrently. - - The other thing that has changed is that most of the code with - incorrect locking has now been fixed. The value of the assert is - accordingly lower. - - However, remaining broken callers do need to be fixed. That's why - libXCB will still noisily print a stacktrace (if possible) on each - assertion failure, even when assert isn't actually invoked to - abort() the program; and that's why aborting is still default. This - environment variable is provided only for use as a temporary - workaround for broken applications. - -Enhancements: -* Print a backtrace, if possible, on locking assertion failures. -* Skip abort() on locking assertions if LIBXCB_ALLOW_SLOPPY_LOCK is set. -* xcb_poll_for_event: Return already-read events before reading again. -* Output a configuration summary at the end of ./configure. - -Bug fixes: -* Don't hold the xlib-xcb lock while sleeping: that allows deadlock. -* Allow unix: style display names again. -* Bug #9119: test xcb_popcount -* Fix unit tests for FreeBSD -* NetBSD doesn't have AI_ADDRCONFIG: use it only if it's available. -* Require libXau >= 0.99.2; earlier versions have a broken .pc file -* Use substitition variables in xcb-xinerama.pc.in -* Update autogen.sh to one that does objdir != srcdir -* Add tools/* and autogen.sh to EXTRA_DIST. -* Doxygen can now be fully disabled if desired. - -Documentation improvements: -* Many fixes and updates to the tutorial. -* Iterators, requests, and replies get partial Doxygen documentation. - - -Release 1.0 (2006-11-23) -======================== - -The "Thanksgiving" release: We feel thankful to have it released. Five years -have passed since XCB's initial commit on September 3rd, 2001: - - -* Support IPv6. XCB now supports displays with IPv6 addresses, with or without - enclosing square brackets, or with hosts which resolve to IPv6 addresses, by - using getaddrinfo instead of gethostbyname, and by including support for - authentication for such connections. This allows such displays as "::1:1.1". - -* XCB now uses the libpthread-stubs, to properly support optional use of - pthreads even on platforms which do not have all the necessary pthread stubs - in libc or otherwise available by default. - -* Switch from the old AM_PATH_CHECK macro to pkg-config. check 0.9.4 is now - required to build XCB's unit tests. The version that we were requiring was - not actually new enough to let our unit tests compile, and the AM_PATH_CHECK - macro is now considered deprecated. We know that versions of check using - pkg-config are new enough to work, and the check dependency was optional - anyway, so we've dropped support for older versions. - -* Provide a xcb_prefetch_maximum_request_length counterpart to - xcb_get_maximum_request_length. - -* Fix Bug #5958: zero out padding bytes in requests. - -* Change xcb_connect to pass the display number to _xcb_get_auth_info, which - passes it to get_authptr. This allows get_authptr to stop hacking the - display number out of the sockaddrs of various address families, such as - port - X_TCP_PORT, or the number after the last X in the UNIX socket path. - -* Remove --with-opt and --with-debug options from configure.ac; configure - supports the use of custom CFLAGS, so please use that instead. - -* Reove support for the tag in protocol descriptions, since they - no longer use it, and since new protocol descriptions should not need it - either. - -* xcb-proto has no libraries or headers, so don't use XCBPROTO_CFLAGS or - XCBPROTO_LIBS. - -* XCB builds which use xdmcp now include it in Requires.private, to support - static linking. - -* Replace "long" with uint32_t when used for a 32-bit quantity - -* Various enhancements to the generation of documentation with Doxygen: - * Check for doxygen in configure.ac - * Fix some Doxygen warnings. - * Install documentation. - * Handle out-of-tree builds, with srcdir != builddir. xcb.doxygen now gets - generated from xcb.doxygen.in, so that it can use top_builddir and - top_srcdir to find source and to output documentation. - * Fill in PROJECT_NUMBER from @VERSION@, now that we have it readily - available via autoconf. - - -Release 1.0 RC3 (2006-11-02) -============================ - -Note: Version 0.9.4 of the test suite tool "check" provides a broken -version of the AM_PATH_CHECK macro, which causes autoconf to fail due to -insufficient quoting on the macro names it prints in its deprecation -message. We have written a patch to fix this problem, available at: - -Version 0.9.4-2 of the Debian package for check includes this patch. -Users of other distributions who want to re-autotool libxcb will need to -apply this patch, use an older version of check, or wait for a fixed -upstream version. This bug does not affect users who use the distributed -tarballs and do not re-autotool. - -* Add library support for xcb-xinerama, using new protocol description - from xcb-proto. -* In the generated protocol code, define and use constants for opcode - numbers rather than hard-coding them. -* In the API conversion script, match only XCB-namespaced XID generators - when converting to xcb_generate_id. -* Quit treating xproto specially in Makefile.am: handle it like all the - extensions. -* Generate Doxygen documentation comments in the protocol stubs, and - provide a Doxygen config file for building HTML documentation for XCB. -* Add note to xcbxlib.h that nothing except Xlib/XCB should use it. -* Extend test suite to test xcb_parse_display with NULL argument and - display in $DISPLAY. - - -Release 1.0 RC2 (2006-10-07) -============================ - -API changes ------------ - -In our announcement of XCB 1.0 RC1, we proposed two API changes for -community feedback: - - We would greatly appreciate API review in this final release - candidate period. We've had some limited feedback that our attempts - to impose static type safety on XIDs in C pose more a hindrance than - a help, so we would appreciate discussion over whether this - constitutes a "serious issue with the API". Some question also - remains of whether xcb_poll_for_event should have the out-parameter - 'error', now that XCB has a more uniform mechanism for reporting - connection errors. Speak now on these points or leave us alone. ;-) - -Since we've received feedback agreeing with our proposed changes, and no -objections or requests to keep the existing API, we made both changes -and bumped the soname to libxcb.so.1.0.0 in preparation for the release -of XCB 1.0. - -* Remove XID wrapper structures and replace them with uint32_t typedefs. - XID union types like xcb_drawable_t and xcb_fontable_t also become - uint32_t typedefs. The API conversion script now replaces xcb_*_new - with calls directly to xcb_generate_id. This change makes - xcb_generate_id part of the client API rather than the extension API, - so move xcb_generate_id from xcbext.h to xcb.h. - -* Remove the 'int *error' out-parameter for xcb_poll_for_event. - xcb_poll_for_event now shuts down the xcb_connection_t on fatal - errors; use xcb_connection_has_error to check. - -The Xlib-specific API in libxcb-xlib also changed: - -* Stop exposing the XCB IO lock for Xlib's benefit, by removing - xcb_get_io_lock from the Xlib-specific XCB API; instead, libxcb-xlib - now provides xcb_xlib_lock and xcb_xlib_unlock. - -Code generation changes ------------------------ - -* The code generator no longer implicitly imports xproto for extensions. - xcb-proto 1.0 RC2 includes the corresponding change to explicitly - import xproto in extensions that need it - -* The generated protocol headers now declare "struct foo", "union foo" - or "enum foo", not just the typedef "foo" of an unnamed - struct/union/enum type. - -Bug Fixes ---------- - -* Make Plan 7 'checked' requests work correctly. - -Documentation improvements --------------------------- - -* Document xcb_generate_id. - -* Tutorial enhancements. - - -Release 1.0 RC1 (2006-09-25) -============================ - -The Great XCB Renaming ----------------------- - -Rename API to follow a new naming convention: - -* XCB_CONSTANTS_UPPERCASE_WITH_UNDERSCORES -* xcb_functions_lowercase_with_underscores -* xcb_types_lowercase_with_underscores_and_suffix_t -* expand all abbreviations like "req", "rep", and "iter" - -Word boundaries for the names in the protocol descriptions fall: - -* Wherever the protocol descriptions already have an underscore -* Between a lowercase letter and a subsequent uppercase letter -* Before the last uppercase letter in a string of uppercase letters - followed by a lowercase letter (such as in LSBFirst between LSB and - First) -* Before and after a string of digits (with exceptions for sized types - like xcb_char2b_t and xcb_glx_float32_t to match the stdint.h - convention) - -Also fix up some particular naming issues: - -* Rename shape_op and shape_kind to drop the "shape_" prefix, since - otherwise these types end up as xcb_shape_shape_{op,kind}_t. -* Remove leading underscores from enums in the GLX protocol description, - previously needed to ensure a word separator, but now redundant. - -This renaming breaks code written for the previous API naming -convention. The scripts in XCB's tools directory will convert code -written for the old API to use the new API; they work well enough that -we used them to convert the non-program-generated code in XCB, and when -run on the old program-generated code, they almost exactly reproduce the -new program-generated code (modulo whitespace and bugs in the old code -generator). - -Authors: Vincent Torri, Thomas Hunger, Josh Triplett - -In addition to the API renaming, the library SONAMEs have changed to -libxcb.so and libxcb-extname.so. The library major version remains at 0, -to become version 1 before 1.0 is released; the SONAME lowercasing means -that this will not conflict with XCB 0.9 libraries. - -The header files have moved from /usr/include/X11/XCB/ to -/usr/include/xcb/. The XML-XCB protocol descriptions have moved to -/usr/share/xcb, with extension descriptions no longer relegated to an -extensions/ subdirectory. The API conversion script api_conv.pl will fix -references to the header files, and packages using pkg-config will -automatically use the new library names. - -Error handling Plan 7 ---------------------- - -All request functions now come in an "unchecked" and "checked" variant. -The checked variant allows callers to handle errors inline where they -obtain the reply, or by calling xcb_request_check for requests with no -reply. The unchecked variant uses the event queue for errors. Requests -with replies default to checked, because the caller must already make a -function call to retrieve the reply and can see the error at that time; -the unchecked variant uses the suffix _unchecked. Requests without -replies default to unchecked, because the caller will not necessarily -expect to handle a response, and the checked variant uses the suffix -_checked. - -Connection error handling -------------------------- - -Fatal connection errors now put the xcb_connection_t object into an -error state, at which point all further operations on that connection -will fail. Callers can use the new xcb_connection_has_error function to -check for this state in a connection. Functions that return a -connection, such as the xcb_connect function, may instead return an -xcb_connection_t already in an error state. - -In the future we expect to add additional API for getting more -information about the error condition that caused the connection to get -into an error state. - -Smaller API changes -------------------- - -All functions that have been marked 'deprecated' up to now have been -removed for this release. After XCB 1.0 is released, functions marked -'deprecated' will be preserved until the end of time to maintain -compatibility. - -XCB no longer provides a sync function. Most callers of this function -should use xcb_flush instead, which usually provides the intended -functionality and does not require a round-trip to the server. If you -really need this functionality, either use xcb_get_input_focus like sync -used to do, or use the xcb_aux_sync function from the xcb-aux library in -xcb-util. However, note that we do not consider the libraries in -xcb-util remotely stable yet. - -XCB no longer provides xcb_[extension_name]_init functions for each -extension. These functions previously caused XCB to issue and process a -QueryExtension request. Callers should now directly call -xcb_get_extension_data on the xcb_[extension_name]_id, or use -xcb_prefetch_extension_data if they do not need to force a round-trip -immediately. - -The compatibility functions in xcbxlib.h, provided solely for use by -Xlib/XCB, now exist in a separate library libxcb-xlib. We don't want to -have to change the libxcb soname if we later change or remove the Xlib -compatibility functions, and nothing except Xlib/XCB should ever use -them. (Applications which use Xlib/XCB do not need this library either; -Xlib/XCB only uses it internally.) - -The descriptions of several extensions have been updated to match the -latest versions implemented in the X.org X server. - -GIT Repository split --------------------- - -Previously, several XCB-related projects all existed under the umbrella -of a single monolithic GIT repository with per-project subdirectories. -We have split this repository into individual per-project repositories. - -Josh Triplett and Jamey Sharp wrote a tool called git-split to -accomplish this repository split. git-split reconstructs the history of -a sub-project previously stored in a subdirectory of a larger -repository. It constructs new commit objects based on the existing tree -objects for the subtree in each commit, and discards commits which do -not affect the history of the sub-project, as well as merges made -unnecessary due to these discarded commits. - -We would like to acknowledge the work of the gobby team in creating a -collaborative editor which greatly aided the development of git-split -(as well as these release notes). - -Build and implementation fixes ------------------------------- - -XCB no longer needs proto/x11 from X.org; the XCB header xproto.h -provides the definitions from X.h, named according to XCB conventions. - -XCB should now build with non-GNU implementations of Make. - -XCB properly handles 32-bit wrap of sequence numbers, and thus now -supports issuing more than 2**32 requests in one connection. - -Fixed bugs #7001, #7261. +Release 1.8 (2012-01-11) +======================== +- xcb_disconnect: call shutdown() to force a disconnect +- Use special path to sockets when running under Solaris Trusted Extensions +- Remove unused DECnet code +- Add #include to xcb_conn.c +- Make launchd code in xcb_util.c match surrounding code indent levels +- If protocol is "unix", use a Unix domain socket, not TCP +- Added more error states and removed global error_connection +- Handle XGE events with the "send event" flag +- added xcb_sumof() with restriction to uint8_t +- xkb: updated configure.ac/Makefile.am +- xkb: added pkg config file +- special case 'intermixed variable and fixed size fields': fixed reply side, needs testing +- added accessors for special cases +- Add support for building with Python 3 +- Insert, not append explicit xcbgen dir python path +- xcb_request_check: Sync even if an event was read for this sequence. +- _xcb_conn_wait: Shut down the connection on unexpected poll() events. +- xcb_send_request: Send all requests using a common internal send_request. +- xcb_request_check: Hold the I/O lock while deciding to sync. +- xcb_discard_reply: Simplify by re-using poll_for_reply helper. +- xcb_in: Use 64-bit sequence numbers internally everywhere. +- Enable AM_SILENT_RULES on automake 1.11 or newer. +- Factor reader_list management out of wait_for_reply. +- Dequeue readers that can't receive any new responses. +- Delete the old c-client.xsl. +- Keep ALIGNOF definition out of the public namespace. +- darwin: Don't use poll() when expected to run on darwin10 and prior +- Add Win32 +- Allow disconnecting connections that are in error state. +- Make xcb_take_socket keep flushing until idle +- Support pre-IPv6 systems (without getaddrinfo) +- Drop AI_ADDRCONFIG when resolving TCP addresses +- xcb_auth: Fix memory leak in _xcb_get_auth_info. +- Don't emit out-of-module sizeof definitions +- Clean up a couple of warnings in xprint +- Prevent reply waiters from being blocked. +- Prevent theoretical double free and leak on get_peer_sock_name. +- Introduce a variant of xcb_poll_for_event for examining event queue. +- xcb_take_socket: Document sequence wrap requirements +- Compute alignment correctly +- Fix a dead-lock due to xcb_poll_for_reply + + +Release 1.7 (2010-08-13) +======================== +- Always wake up readers after writing +- Get rid of PATH_MAX and MAXPATHLEN +- Add ~ operator support in code generator +- xcb_open: Improve protocol/host parsing +- xcb_connect_to_display_with_auth_info: Fix memory leak +- Report which extensions are being built + +Release 1.6 (2010-04-09) +======================== +- darwin: xnu doesn't support poll on ttys on the master side +- Fix descriptor leak on memory error path +- Support xcb_discard_reply +- Open the X11 socket with close-on-exec flag +- Fix authentication on hpux and Hurd + +Release 1.5 (2009-12-03) +======================== +- setsockopt(SO_KEEPALIVE) on TCP display connections +- Add DRI2 support +- Fix check dependency +- Cygwin build fix: Add -no-undefined to libtool flags + +Release 1.4 (2009-07-15) +======================== +* Add majorCode, minorCode and resourceID fields to X generic error +* Fix precedence bug: wrong length for big-requests preceded by sync +* Fix libxcb-randr version info + +Release 1.3 (2009-05-29) +======================== +* Copy full IPv4 mapping (Bug #20665) +* Fix XID allocation +* Use poll() instead of select() when available +* Fix local socket connection on Hurd +* Fix XDM-AUTHORIZATION-1 +* Disable Nagle on TCP socket + +Release 1.2 (2009-02-17) +======================== +* Stop packaging auto-generated C files into tarball. + +Release 1.1.93 (2008-12-11) +=========================== +Enhancements: +* Apple: Enable support for launchd DISPLAY socket +* Treat XIDs the same as other cardinal values. + +Release 1.1.92 (2008-11-01) +=========================== +Enhancements: +* Added small fix to support trailing fixed fields; also warning for non-pad fixed fields +* Fixed overly aggressive warning about fixed field following variable +* Added generation of extern "C" for compatibility with C++ +* Remove libxcb-xlib and xcbxlib.h. +* Inline _xcb_lock_io, _xcb_unlock_io, and _xcb_wait_io. +* Track 64-bit sequence numbers internally. +* Use sequence number ranges in pending replies +* Remove duplicate XCB_EXTENSION calls for Composite extension +* Factorize m4 macros and add one to set X extensions +* Allow compile-time setting for XCB queue buffer size +* Support handing off socket write permission to external code. +* Add support for the abstract socket namespace under Linux + +Bug fixes: +* Fix tiny memory leak in read_packet +* Fix some fd leaks in _xcb_open_*() + +Release 1.1 (2007-11-04) +======================== + +This release requires xcb-proto 1.1, due to the addition of the +extension-multiword attribute to the XML schema. + +This release contains several important bug fixes, summarized below. It +also contains a patch much like Novell's libxcb-sloppy-lock.diff. +Rationale from the commit message follows. The patch and this rationale +were authored by Jamey Sharp , with agreement from +Josh Triplett . + + I strongly opposed proposals like this one for a long time. + Originally I had a very good reason: libX11, when compiled to use + XCB, would crash soon after a locking correctness violation, so it + was better to have an informative assert failure than a mystifying + crash soon after. + + It took some time for me to realize that I'd changed the libX11 + implementation (for unrelated reasons) so that it could survive most + invalid locking situations, as long as it wasn't actually being used + from multiple threads concurrently. + + The other thing that has changed is that most of the code with + incorrect locking has now been fixed. The value of the assert is + accordingly lower. + + However, remaining broken callers do need to be fixed. That's why + libXCB will still noisily print a stacktrace (if possible) on each + assertion failure, even when assert isn't actually invoked to + abort() the program; and that's why aborting is still default. This + environment variable is provided only for use as a temporary + workaround for broken applications. + +Enhancements: +* Print a backtrace, if possible, on locking assertion failures. +* Skip abort() on locking assertions if LIBXCB_ALLOW_SLOPPY_LOCK is set. +* xcb_poll_for_event: Return already-read events before reading again. +* Output a configuration summary at the end of ./configure. + +Bug fixes: +* Don't hold the xlib-xcb lock while sleeping: that allows deadlock. +* Allow unix: style display names again. +* Bug #9119: test xcb_popcount +* Fix unit tests for FreeBSD +* NetBSD doesn't have AI_ADDRCONFIG: use it only if it's available. +* Require libXau >= 0.99.2; earlier versions have a broken .pc file +* Use substitition variables in xcb-xinerama.pc.in +* Update autogen.sh to one that does objdir != srcdir +* Add tools/* and autogen.sh to EXTRA_DIST. +* Doxygen can now be fully disabled if desired. + +Documentation improvements: +* Many fixes and updates to the tutorial. +* Iterators, requests, and replies get partial Doxygen documentation. + + +Release 1.0 (2006-11-23) +======================== + +The "Thanksgiving" release: We feel thankful to have it released. Five years +have passed since XCB's initial commit on September 3rd, 2001: + + +* Support IPv6. XCB now supports displays with IPv6 addresses, with or without + enclosing square brackets, or with hosts which resolve to IPv6 addresses, by + using getaddrinfo instead of gethostbyname, and by including support for + authentication for such connections. This allows such displays as "::1:1.1". + +* XCB now uses the libpthread-stubs, to properly support optional use of + pthreads even on platforms which do not have all the necessary pthread stubs + in libc or otherwise available by default. + +* Switch from the old AM_PATH_CHECK macro to pkg-config. check 0.9.4 is now + required to build XCB's unit tests. The version that we were requiring was + not actually new enough to let our unit tests compile, and the AM_PATH_CHECK + macro is now considered deprecated. We know that versions of check using + pkg-config are new enough to work, and the check dependency was optional + anyway, so we've dropped support for older versions. + +* Provide a xcb_prefetch_maximum_request_length counterpart to + xcb_get_maximum_request_length. + +* Fix Bug #5958: zero out padding bytes in requests. + +* Change xcb_connect to pass the display number to _xcb_get_auth_info, which + passes it to get_authptr. This allows get_authptr to stop hacking the + display number out of the sockaddrs of various address families, such as + port - X_TCP_PORT, or the number after the last X in the UNIX socket path. + +* Remove --with-opt and --with-debug options from configure.ac; configure + supports the use of custom CFLAGS, so please use that instead. + +* Reove support for the tag in protocol descriptions, since they + no longer use it, and since new protocol descriptions should not need it + either. + +* xcb-proto has no libraries or headers, so don't use XCBPROTO_CFLAGS or + XCBPROTO_LIBS. + +* XCB builds which use xdmcp now include it in Requires.private, to support + static linking. + +* Replace "long" with uint32_t when used for a 32-bit quantity + +* Various enhancements to the generation of documentation with Doxygen: + * Check for doxygen in configure.ac + * Fix some Doxygen warnings. + * Install documentation. + * Handle out-of-tree builds, with srcdir != builddir. xcb.doxygen now gets + generated from xcb.doxygen.in, so that it can use top_builddir and + top_srcdir to find source and to output documentation. + * Fill in PROJECT_NUMBER from @VERSION@, now that we have it readily + available via autoconf. + + +Release 1.0 RC3 (2006-11-02) +============================ + +Note: Version 0.9.4 of the test suite tool "check" provides a broken +version of the AM_PATH_CHECK macro, which causes autoconf to fail due to +insufficient quoting on the macro names it prints in its deprecation +message. We have written a patch to fix this problem, available at: + +Version 0.9.4-2 of the Debian package for check includes this patch. +Users of other distributions who want to re-autotool libxcb will need to +apply this patch, use an older version of check, or wait for a fixed +upstream version. This bug does not affect users who use the distributed +tarballs and do not re-autotool. + +* Add library support for xcb-xinerama, using new protocol description + from xcb-proto. +* In the generated protocol code, define and use constants for opcode + numbers rather than hard-coding them. +* In the API conversion script, match only XCB-namespaced XID generators + when converting to xcb_generate_id. +* Quit treating xproto specially in Makefile.am: handle it like all the + extensions. +* Generate Doxygen documentation comments in the protocol stubs, and + provide a Doxygen config file for building HTML documentation for XCB. +* Add note to xcbxlib.h that nothing except Xlib/XCB should use it. +* Extend test suite to test xcb_parse_display with NULL argument and + display in $DISPLAY. + + +Release 1.0 RC2 (2006-10-07) +============================ + +API changes +----------- + +In our announcement of XCB 1.0 RC1, we proposed two API changes for +community feedback: + + We would greatly appreciate API review in this final release + candidate period. We've had some limited feedback that our attempts + to impose static type safety on XIDs in C pose more a hindrance than + a help, so we would appreciate discussion over whether this + constitutes a "serious issue with the API". Some question also + remains of whether xcb_poll_for_event should have the out-parameter + 'error', now that XCB has a more uniform mechanism for reporting + connection errors. Speak now on these points or leave us alone. ;-) + +Since we've received feedback agreeing with our proposed changes, and no +objections or requests to keep the existing API, we made both changes +and bumped the soname to libxcb.so.1.0.0 in preparation for the release +of XCB 1.0. + +* Remove XID wrapper structures and replace them with uint32_t typedefs. + XID union types like xcb_drawable_t and xcb_fontable_t also become + uint32_t typedefs. The API conversion script now replaces xcb_*_new + with calls directly to xcb_generate_id. This change makes + xcb_generate_id part of the client API rather than the extension API, + so move xcb_generate_id from xcbext.h to xcb.h. + +* Remove the 'int *error' out-parameter for xcb_poll_for_event. + xcb_poll_for_event now shuts down the xcb_connection_t on fatal + errors; use xcb_connection_has_error to check. + +The Xlib-specific API in libxcb-xlib also changed: + +* Stop exposing the XCB IO lock for Xlib's benefit, by removing + xcb_get_io_lock from the Xlib-specific XCB API; instead, libxcb-xlib + now provides xcb_xlib_lock and xcb_xlib_unlock. + +Code generation changes +----------------------- + +* The code generator no longer implicitly imports xproto for extensions. + xcb-proto 1.0 RC2 includes the corresponding change to explicitly + import xproto in extensions that need it + +* The generated protocol headers now declare "struct foo", "union foo" + or "enum foo", not just the typedef "foo" of an unnamed + struct/union/enum type. + +Bug Fixes +--------- + +* Make Plan 7 'checked' requests work correctly. + +Documentation improvements +-------------------------- + +* Document xcb_generate_id. + +* Tutorial enhancements. + + +Release 1.0 RC1 (2006-09-25) +============================ + +The Great XCB Renaming +---------------------- + +Rename API to follow a new naming convention: + +* XCB_CONSTANTS_UPPERCASE_WITH_UNDERSCORES +* xcb_functions_lowercase_with_underscores +* xcb_types_lowercase_with_underscores_and_suffix_t +* expand all abbreviations like "req", "rep", and "iter" + +Word boundaries for the names in the protocol descriptions fall: + +* Wherever the protocol descriptions already have an underscore +* Between a lowercase letter and a subsequent uppercase letter +* Before the last uppercase letter in a string of uppercase letters + followed by a lowercase letter (such as in LSBFirst between LSB and + First) +* Before and after a string of digits (with exceptions for sized types + like xcb_char2b_t and xcb_glx_float32_t to match the stdint.h + convention) + +Also fix up some particular naming issues: + +* Rename shape_op and shape_kind to drop the "shape_" prefix, since + otherwise these types end up as xcb_shape_shape_{op,kind}_t. +* Remove leading underscores from enums in the GLX protocol description, + previously needed to ensure a word separator, but now redundant. + +This renaming breaks code written for the previous API naming +convention. The scripts in XCB's tools directory will convert code +written for the old API to use the new API; they work well enough that +we used them to convert the non-program-generated code in XCB, and when +run on the old program-generated code, they almost exactly reproduce the +new program-generated code (modulo whitespace and bugs in the old code +generator). + +Authors: Vincent Torri, Thomas Hunger, Josh Triplett + +In addition to the API renaming, the library SONAMEs have changed to +libxcb.so and libxcb-extname.so. The library major version remains at 0, +to become version 1 before 1.0 is released; the SONAME lowercasing means +that this will not conflict with XCB 0.9 libraries. + +The header files have moved from /usr/include/X11/XCB/ to +/usr/include/xcb/. The XML-XCB protocol descriptions have moved to +/usr/share/xcb, with extension descriptions no longer relegated to an +extensions/ subdirectory. The API conversion script api_conv.pl will fix +references to the header files, and packages using pkg-config will +automatically use the new library names. + +Error handling Plan 7 +--------------------- + +All request functions now come in an "unchecked" and "checked" variant. +The checked variant allows callers to handle errors inline where they +obtain the reply, or by calling xcb_request_check for requests with no +reply. The unchecked variant uses the event queue for errors. Requests +with replies default to checked, because the caller must already make a +function call to retrieve the reply and can see the error at that time; +the unchecked variant uses the suffix _unchecked. Requests without +replies default to unchecked, because the caller will not necessarily +expect to handle a response, and the checked variant uses the suffix +_checked. + +Connection error handling +------------------------- + +Fatal connection errors now put the xcb_connection_t object into an +error state, at which point all further operations on that connection +will fail. Callers can use the new xcb_connection_has_error function to +check for this state in a connection. Functions that return a +connection, such as the xcb_connect function, may instead return an +xcb_connection_t already in an error state. + +In the future we expect to add additional API for getting more +information about the error condition that caused the connection to get +into an error state. + +Smaller API changes +------------------- + +All functions that have been marked 'deprecated' up to now have been +removed for this release. After XCB 1.0 is released, functions marked +'deprecated' will be preserved until the end of time to maintain +compatibility. + +XCB no longer provides a sync function. Most callers of this function +should use xcb_flush instead, which usually provides the intended +functionality and does not require a round-trip to the server. If you +really need this functionality, either use xcb_get_input_focus like sync +used to do, or use the xcb_aux_sync function from the xcb-aux library in +xcb-util. However, note that we do not consider the libraries in +xcb-util remotely stable yet. + +XCB no longer provides xcb_[extension_name]_init functions for each +extension. These functions previously caused XCB to issue and process a +QueryExtension request. Callers should now directly call +xcb_get_extension_data on the xcb_[extension_name]_id, or use +xcb_prefetch_extension_data if they do not need to force a round-trip +immediately. + +The compatibility functions in xcbxlib.h, provided solely for use by +Xlib/XCB, now exist in a separate library libxcb-xlib. We don't want to +have to change the libxcb soname if we later change or remove the Xlib +compatibility functions, and nothing except Xlib/XCB should ever use +them. (Applications which use Xlib/XCB do not need this library either; +Xlib/XCB only uses it internally.) + +The descriptions of several extensions have been updated to match the +latest versions implemented in the X.org X server. + +GIT Repository split +-------------------- + +Previously, several XCB-related projects all existed under the umbrella +of a single monolithic GIT repository with per-project subdirectories. +We have split this repository into individual per-project repositories. + +Josh Triplett and Jamey Sharp wrote a tool called git-split to +accomplish this repository split. git-split reconstructs the history of +a sub-project previously stored in a subdirectory of a larger +repository. It constructs new commit objects based on the existing tree +objects for the subtree in each commit, and discards commits which do +not affect the history of the sub-project, as well as merges made +unnecessary due to these discarded commits. + +We would like to acknowledge the work of the gobby team in creating a +collaborative editor which greatly aided the development of git-split +(as well as these release notes). + +Build and implementation fixes +------------------------------ + +XCB no longer needs proto/x11 from X.org; the XCB header xproto.h +provides the definitions from X.h, named according to XCB conventions. + +XCB should now build with non-GNU implementations of Make. + +XCB properly handles 32-bit wrap of sequence numbers, and thus now +supports issuing more than 2**32 requests in one connection. + +Fixed bugs #7001, #7261. diff --git a/libxcb/configure.ac b/libxcb/configure.ac index cba9dbdad..9abaffced 100644 --- a/libxcb/configure.ac +++ b/libxcb/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.57) AC_INIT([libxcb], - 1.7, + 1.8, [xcb@lists.freedesktop.org]) AC_CONFIG_SRCDIR([xcb.pc.in]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) @@ -34,7 +34,7 @@ fi AC_SUBST(HTML_CHECK_RESULT) # Checks for pkg-config packages -PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.6) +PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.7) NEEDED="pthread-stubs xau >= 0.99.2" PKG_CHECK_MODULES(NEEDED, $NEEDED) diff --git a/libxcb/src/xcb.h b/libxcb/src/xcb.h index 3ee7965d2..44f650ad7 100644 --- a/libxcb/src/xcb.h +++ b/libxcb/src/xcb.h @@ -69,6 +69,21 @@ extern "C" { /** X_TCP_PORT + display number = server port for TCP transport */ #define X_TCP_PORT 6000 +/** xcb connection errors because of socket, pipe and other stream errors. */ +#define XCB_CONN_ERROR 1 + +/** xcb connection shutdown because of extension not sppported */ +#define XCB_CONN_CLOSED_EXT_NOTSUPPORTED 2 + +/** malloc(), calloc() and realloc() error upon failure, for eg ENOMEM */ +#define XCB_CONN_CLOSED_MEM_INSUFFICIENT 3 + +/** Connection closed, exceeding request length that server accepts. */ +#define XCB_CONN_CLOSED_REQ_LEN_EXCEED 4 + +/** Connection closed, error during parsing display string. */ +#define XCB_CONN_CLOSED_PARSE_ERR 5 + #define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1)) /* Opaque structures */ @@ -396,15 +411,18 @@ int xcb_get_file_descriptor(xcb_connection_t *c); /** * @brief Test whether the connection has shut down due to a fatal error. * @param c: The connection. - * @return 1 if the connection is in an error state; 0 otherwise. + * @return > 0 if the connection is in an error state; 0 otherwise. * * Some errors that occur in the context of an xcb_connection_t * are unrecoverable. When such an error occurs, the * connection is shut down and further operations on the * xcb_connection_t have no effect. * - * @todo Other functions should document the conditions in - * which they shut down the connection. + * @return XCB_CONN_ERROR, because of socket errors, pipe errors or other stream errors. + * @return XCB_CONN_CLOSED_EXT_NOTSUPPORTED, when extension not supported. + * @return XCB_CONN_CLOSED_MEM_INSUFFICIENT, when memory not available. + * @return XCB_CONN_CLOSED_REQ_LEN_EXCEED, exceeding request length that server accepts. + * @return XCB_CONN_CLOSED_PARSE_ERR, error during parsing display string. */ int xcb_connection_has_error(xcb_connection_t *c); diff --git a/libxcb/src/xcb_auth.c b/libxcb/src/xcb_auth.c index 859ab8a76..ea4ad8f6a 100644 --- a/libxcb/src/xcb_auth.c +++ b/libxcb/src/xcb_auth.c @@ -30,16 +30,20 @@ #include #include #include -#include #ifdef __INTERIX /* _don't_ ask. interix has INADDR_LOOPBACK in here. */ #include #endif +#ifdef HASXDMAUTH +#include +#endif + #ifdef _WIN32 #include "xcb_windefs.h" #else +#include #include #include #include @@ -48,9 +52,6 @@ #include "xcb.h" #include "xcbint.h" -#ifdef HASXDMAUTH -#include -#endif enum auth_protos { #ifdef HASXDMAUTH diff --git a/libxcb/src/xcb_conn.c b/libxcb/src/xcb_conn.c index 84a9917d6..725502af6 100644 --- a/libxcb/src/xcb_conn.c +++ b/libxcb/src/xcb_conn.c @@ -1,410 +1,441 @@ -/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp. - * - * 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 - * AUTHORS 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 names of the authors or their - * institutions 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 authors. - */ - -/* Connection management: the core of XCB. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "xcb.h" -#include "xcbint.h" -#if USE_POLL -#include -#elif !defined _WIN32 -#include -#endif - -#ifdef _WIN32 -#include "xcb_windefs.h" -#else -#include -#include -#endif /* _WIN32 */ - -/* SHUT_RDWR is fairly recent and is not available on all platforms */ -#if !defined(SHUT_RDWR) -#define SHUT_RDWR 2 -#endif - -typedef struct { - uint8_t status; - uint8_t pad0[5]; - uint16_t length; -} xcb_setup_generic_t; - -const int error_connection = 1; - -static int set_fd_flags(const int fd) -{ -/* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */ - -#ifdef _WIN32 - u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */ - int ret = 0; - - ret = ioctlsocket(fd, FIONBIO, &iMode); - if(ret != 0) - return 0; - return 1; -#else - int flags = fcntl(fd, F_GETFL, 0); - if(flags == -1) - return 0; - flags |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flags) == -1) - return 0; - if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - return 0; - return 1; -#endif /* _WIN32 */ -} - -static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info) -{ - static const char pad[3]; - xcb_setup_request_t out; - struct iovec parts[6]; - int count = 0; - static const uint32_t endian = 0x01020304; - int ret; - - memset(&out, 0, sizeof(out)); - - /* B = 0x42 = MSB first, l = 0x6c = LSB first */ - if(htonl(endian) == endian) - out.byte_order = 0x42; - else - out.byte_order = 0x6c; - out.protocol_major_version = X_PROTOCOL; - out.protocol_minor_version = X_PROTOCOL_REVISION; - out.authorization_protocol_name_len = 0; - out.authorization_protocol_data_len = 0; - parts[count].iov_len = sizeof(xcb_setup_request_t); - parts[count++].iov_base = &out; - parts[count].iov_len = XCB_PAD(sizeof(xcb_setup_request_t)); - parts[count++].iov_base = (char *) pad; - - if(auth_info) - { - parts[count].iov_len = out.authorization_protocol_name_len = auth_info->namelen; - parts[count++].iov_base = auth_info->name; - parts[count].iov_len = XCB_PAD(out.authorization_protocol_name_len); - parts[count++].iov_base = (char *) pad; - parts[count].iov_len = out.authorization_protocol_data_len = auth_info->datalen; - parts[count++].iov_base = auth_info->data; - parts[count].iov_len = XCB_PAD(out.authorization_protocol_data_len); - parts[count++].iov_base = (char *) pad; - } - assert(count <= (int) (sizeof(parts) / sizeof(*parts))); - - pthread_mutex_lock(&c->iolock); - ret = _xcb_out_send(c, parts, count); - pthread_mutex_unlock(&c->iolock); - return ret; -} - -static int read_setup(xcb_connection_t *c) -{ - /* Read the server response */ - c->setup = malloc(sizeof(xcb_setup_generic_t)); - if(!c->setup) - return 0; - - if(_xcb_in_read_block(c, c->setup, sizeof(xcb_setup_generic_t)) != sizeof(xcb_setup_generic_t)) - return 0; - - { - void *tmp = realloc(c->setup, c->setup->length * 4 + sizeof(xcb_setup_generic_t)); - if(!tmp) - return 0; - c->setup = tmp; - } - - if(_xcb_in_read_block(c, (char *) c->setup + sizeof(xcb_setup_generic_t), c->setup->length * 4) <= 0) - return 0; - - /* 0 = failed, 2 = authenticate, 1 = success */ - switch(c->setup->status) - { - case 0: /* failed */ - { - xcb_setup_failed_t *setup = (xcb_setup_failed_t *) c->setup; - write(STDERR_FILENO, xcb_setup_failed_reason(setup), xcb_setup_failed_reason_length(setup)); - return 0; - } - - case 2: /* authenticate */ - { - xcb_setup_authenticate_t *setup = (xcb_setup_authenticate_t *) c->setup; - write(STDERR_FILENO, xcb_setup_authenticate_reason(setup), xcb_setup_authenticate_reason_length(setup)); - return 0; - } - } - - return 1; -} - -/* precondition: there must be something for us to write. */ -static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count) -{ - int n; - assert(!c->out.queue_len); - -#ifdef _WIN32 - int i = 0; - int ret = 0,err = 0; - struct iovec *vec; - n = 0; - - /* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from - an iovec would require more work and I'm not sure of the benefit....works for now */ - vec = *vector; - while(i < *count) - { - ret = send(c->fd,vec->iov_base,vec->iov_len,0); - if(ret == SOCKET_ERROR) - { - err = WSAGetLastError(); - if(err == WSAEWOULDBLOCK) - { - return 1; - } - } - n += ret; - *vec++; - i++; - } -#else - n = writev(c->fd, *vector, *count); - if(n < 0 && errno == EAGAIN) - return 1; -#endif /* _WIN32 */ - - if(n <= 0) - { - _xcb_conn_shutdown(c); - return 0; - } - - for(; *count; --*count, ++*vector) - { - int cur = (*vector)->iov_len; - if(cur > n) - cur = n; - (*vector)->iov_len -= cur; - (*vector)->iov_base = (char *) (*vector)->iov_base + cur; - n -= cur; - if((*vector)->iov_len) - break; - } - if(!*count) - *vector = 0; - assert(n == 0); - return 1; -} - -/* Public interface */ - -const xcb_setup_t *xcb_get_setup(xcb_connection_t *c) -{ - if(c->has_error) - return 0; - /* doesn't need locking because it's never written to. */ - return c->setup; -} - -int xcb_get_file_descriptor(xcb_connection_t *c) -{ - if(c->has_error) - return -1; - /* doesn't need locking because it's never written to. */ - return c->fd; -} - -int xcb_connection_has_error(xcb_connection_t *c) -{ - /* doesn't need locking because it's read and written atomically. */ - return c->has_error; -} - -xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info) -{ - xcb_connection_t* c; - -#ifndef _WIN32 -#ifndef USE_POLL - if(fd >= FD_SETSIZE) /* would overflow in FD_SET */ - { - close(fd); - return (xcb_connection_t *) &error_connection; - } -#endif -#endif /* !_WIN32*/ - - c = calloc(1, sizeof(xcb_connection_t)); - if(!c) { - close(fd); - return (xcb_connection_t *) &error_connection; - } - - c->fd = fd; - - if(!( - set_fd_flags(fd) && - pthread_mutex_init(&c->iolock, 0) == 0 && - _xcb_in_init(&c->in) && - _xcb_out_init(&c->out) && - write_setup(c, auth_info) && - read_setup(c) && - _xcb_ext_init(c) && - _xcb_xid_init(c) - )) - { - xcb_disconnect(c); - return (xcb_connection_t *) &error_connection; - } - - return c; -} - -void xcb_disconnect(xcb_connection_t *c) -{ - if(c == (xcb_connection_t *) &error_connection) - return; - - free(c->setup); - - /* disallow further sends and receives */ - shutdown(c->fd, SHUT_RDWR); - close(c->fd); - - pthread_mutex_destroy(&c->iolock); - _xcb_in_destroy(&c->in); - _xcb_out_destroy(&c->out); - - _xcb_ext_destroy(c); - _xcb_xid_destroy(c); - - free(c); -} - -/* Private interface */ - -void _xcb_conn_shutdown(xcb_connection_t *c) -{ - c->has_error = 1; -} - -int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count) -{ - int ret; -#if USE_POLL - struct pollfd fd; -#else - fd_set rfds, wfds; -#endif - - /* If the thing I should be doing is already being done, wait for it. */ - if(count ? c->out.writing : c->in.reading) - { - pthread_cond_wait(cond, &c->iolock); - return 1; - } - -#if USE_POLL - memset(&fd, 0, sizeof(fd)); - fd.fd = c->fd; - fd.events = POLLIN; -#else - FD_ZERO(&rfds); - FD_SET(c->fd, &rfds); -#endif - ++c->in.reading; - -#if USE_POLL - if(count) - { - fd.events |= POLLOUT; - ++c->out.writing; - } -#else - FD_ZERO(&wfds); - if(count) - { - FD_SET(c->fd, &wfds); - ++c->out.writing; - } -#endif - - pthread_mutex_unlock(&c->iolock); - do { -#if USE_POLL - ret = poll(&fd, 1, -1); - /* If poll() returns an event we didn't expect, such as POLLNVAL, treat - * it as if it failed. */ - if(ret >= 0 && (fd.revents & ~fd.events)) - { - ret = -1; - break; - } -#else - ret = select(c->fd + 1, &rfds, &wfds, 0, 0); -#endif - } while (ret == -1 && errno == EINTR); - if(ret < 0) - { - _xcb_conn_shutdown(c); - ret = 0; - } - pthread_mutex_lock(&c->iolock); - - if(ret) - { -#if USE_POLL - if((fd.revents & POLLIN) == POLLIN) -#else - if(FD_ISSET(c->fd, &rfds)) -#endif - ret = ret && _xcb_in_read(c); - -#if USE_POLL - if((fd.revents & POLLOUT) == POLLOUT) -#else - if(FD_ISSET(c->fd, &wfds)) -#endif - ret = ret && write_vec(c, vector, count); - } - - if(count) - --c->out.writing; - --c->in.reading; - - return ret; -} +/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp. + * + * 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 + * AUTHORS 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 names of the authors or their + * institutions 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 authors. + */ + +/* Connection management: the core of XCB. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "xcb.h" +#include "xcbint.h" +#if USE_POLL +#include +#elif !defined _WIN32 +#include +#endif + +#ifdef _WIN32 +#include "xcb_windefs.h" +#else +#include +#include +#endif /* _WIN32 */ + +/* SHUT_RDWR is fairly recent and is not available on all platforms */ +#if !defined(SHUT_RDWR) +#define SHUT_RDWR 2 +#endif + +typedef struct { + uint8_t status; + uint8_t pad0[5]; + uint16_t length; +} xcb_setup_generic_t; + +static const int xcb_con_error = XCB_CONN_ERROR; +static const int xcb_con_closed_mem_er = XCB_CONN_CLOSED_MEM_INSUFFICIENT; +static const int xcb_con_closed_parse_er = XCB_CONN_CLOSED_PARSE_ERR; + +static int set_fd_flags(const int fd) +{ +/* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */ + +#ifdef _WIN32 + u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */ + int ret = 0; + + ret = ioctlsocket(fd, FIONBIO, &iMode); + if(ret != 0) + return 0; + return 1; +#else + int flags = fcntl(fd, F_GETFL, 0); + if(flags == -1) + return 0; + flags |= O_NONBLOCK; + if(fcntl(fd, F_SETFL, flags) == -1) + return 0; + if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + return 0; + return 1; +#endif /* _WIN32 */ +} + +static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info) +{ + static const char pad[3]; + xcb_setup_request_t out; + struct iovec parts[6]; + int count = 0; + static const uint32_t endian = 0x01020304; + int ret; + + memset(&out, 0, sizeof(out)); + + /* B = 0x42 = MSB first, l = 0x6c = LSB first */ + if(htonl(endian) == endian) + out.byte_order = 0x42; + else + out.byte_order = 0x6c; + out.protocol_major_version = X_PROTOCOL; + out.protocol_minor_version = X_PROTOCOL_REVISION; + out.authorization_protocol_name_len = 0; + out.authorization_protocol_data_len = 0; + parts[count].iov_len = sizeof(xcb_setup_request_t); + parts[count++].iov_base = &out; + parts[count].iov_len = XCB_PAD(sizeof(xcb_setup_request_t)); + parts[count++].iov_base = (char *) pad; + + if(auth_info) + { + parts[count].iov_len = out.authorization_protocol_name_len = auth_info->namelen; + parts[count++].iov_base = auth_info->name; + parts[count].iov_len = XCB_PAD(out.authorization_protocol_name_len); + parts[count++].iov_base = (char *) pad; + parts[count].iov_len = out.authorization_protocol_data_len = auth_info->datalen; + parts[count++].iov_base = auth_info->data; + parts[count].iov_len = XCB_PAD(out.authorization_protocol_data_len); + parts[count++].iov_base = (char *) pad; + } + assert(count <= (int) (sizeof(parts) / sizeof(*parts))); + + pthread_mutex_lock(&c->iolock); + ret = _xcb_out_send(c, parts, count); + pthread_mutex_unlock(&c->iolock); + return ret; +} + +static int read_setup(xcb_connection_t *c) +{ + /* Read the server response */ + c->setup = malloc(sizeof(xcb_setup_generic_t)); + if(!c->setup) + return 0; + + if(_xcb_in_read_block(c, c->setup, sizeof(xcb_setup_generic_t)) != sizeof(xcb_setup_generic_t)) + return 0; + + { + void *tmp = realloc(c->setup, c->setup->length * 4 + sizeof(xcb_setup_generic_t)); + if(!tmp) + return 0; + c->setup = tmp; + } + + if(_xcb_in_read_block(c, (char *) c->setup + sizeof(xcb_setup_generic_t), c->setup->length * 4) <= 0) + return 0; + + /* 0 = failed, 2 = authenticate, 1 = success */ + switch(c->setup->status) + { + case 0: /* failed */ + { + xcb_setup_failed_t *setup = (xcb_setup_failed_t *) c->setup; + write(STDERR_FILENO, xcb_setup_failed_reason(setup), xcb_setup_failed_reason_length(setup)); + return 0; + } + + case 2: /* authenticate */ + { + xcb_setup_authenticate_t *setup = (xcb_setup_authenticate_t *) c->setup; + write(STDERR_FILENO, xcb_setup_authenticate_reason(setup), xcb_setup_authenticate_reason_length(setup)); + return 0; + } + } + + return 1; +} + +/* precondition: there must be something for us to write. */ +static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count) +{ + int n; + assert(!c->out.queue_len); + +#ifdef _WIN32 + int i = 0; + int ret = 0,err = 0; + struct iovec *vec; + n = 0; + + /* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from + an iovec would require more work and I'm not sure of the benefit....works for now */ + vec = *vector; + while(i < *count) + { + ret = send(c->fd,vec->iov_base,vec->iov_len,0); + if(ret == SOCKET_ERROR) + { + err = WSAGetLastError(); + if(err == WSAEWOULDBLOCK) + { + return 1; + } + } + n += ret; + *vec++; + i++; + } +#else + n = writev(c->fd, *vector, *count); + if(n < 0 && errno == EAGAIN) + return 1; +#endif /* _WIN32 */ + + if(n <= 0) + { + _xcb_conn_shutdown(c, XCB_CONN_ERROR); + return 0; + } + + for(; *count; --*count, ++*vector) + { + int cur = (*vector)->iov_len; + if(cur > n) + cur = n; + (*vector)->iov_len -= cur; + (*vector)->iov_base = (char *) (*vector)->iov_base + cur; + n -= cur; + if((*vector)->iov_len) + break; + } + if(!*count) + *vector = 0; + assert(n == 0); + return 1; +} + +/* Public interface */ + +const xcb_setup_t *xcb_get_setup(xcb_connection_t *c) +{ + if(c->has_error) + return 0; + /* doesn't need locking because it's never written to. */ + return c->setup; +} + +int xcb_get_file_descriptor(xcb_connection_t *c) +{ + if(c->has_error) + return -1; + /* doesn't need locking because it's never written to. */ + return c->fd; +} + +int xcb_connection_has_error(xcb_connection_t *c) +{ + /* doesn't need locking because it's read and written atomically. */ + return c->has_error; +} + +xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info) +{ + xcb_connection_t* c; + +#ifndef _WIN32 +#ifndef USE_POLL + if(fd >= FD_SETSIZE) /* would overflow in FD_SET */ + { + close(fd); + return _xcb_conn_ret_error(XCB_CONN_ERROR); + } +#endif +#endif /* !_WIN32*/ + + c = calloc(1, sizeof(xcb_connection_t)); + if(!c) { + close(fd); + return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ; + } + + c->fd = fd; + + if(!( + set_fd_flags(fd) && + pthread_mutex_init(&c->iolock, 0) == 0 && + _xcb_in_init(&c->in) && + _xcb_out_init(&c->out) && + write_setup(c, auth_info) && + read_setup(c) && + _xcb_ext_init(c) && + _xcb_xid_init(c) + )) + { + xcb_disconnect(c); + return _xcb_conn_ret_error(XCB_CONN_ERROR); + } + + return c; +} + +void xcb_disconnect(xcb_connection_t *c) +{ + if(c->has_error) + return; + + free(c->setup); + + /* disallow further sends and receives */ + shutdown(c->fd, SHUT_RDWR); + close(c->fd); + + pthread_mutex_destroy(&c->iolock); + _xcb_in_destroy(&c->in); + _xcb_out_destroy(&c->out); + + _xcb_ext_destroy(c); + _xcb_xid_destroy(c); + + free(c); + +#ifdef _WIN32 + WSACleanup(); +#endif +} + +/* Private interface */ + +void _xcb_conn_shutdown(xcb_connection_t *c, int err) +{ + c->has_error = err; +} + +/* Return connection error state. + * To make thread-safe, I need a seperate static + * variable for every possible error. + */ +xcb_connection_t *_xcb_conn_ret_error(int err) +{ + + switch(err) + { + case XCB_CONN_CLOSED_MEM_INSUFFICIENT: + { + return (xcb_connection_t *) &xcb_con_closed_mem_er; + } + case XCB_CONN_CLOSED_PARSE_ERR: + { + return (xcb_connection_t *) &xcb_con_closed_parse_er; + } + case XCB_CONN_ERROR: + default: + { + return (xcb_connection_t *) &xcb_con_error; + } + } +} + +int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count) +{ + int ret; +#if USE_POLL + struct pollfd fd; +#else + fd_set rfds, wfds; +#endif + + /* If the thing I should be doing is already being done, wait for it. */ + if(count ? c->out.writing : c->in.reading) + { + pthread_cond_wait(cond, &c->iolock); + return 1; + } + +#if USE_POLL + memset(&fd, 0, sizeof(fd)); + fd.fd = c->fd; + fd.events = POLLIN; +#else + FD_ZERO(&rfds); + FD_SET(c->fd, &rfds); +#endif + ++c->in.reading; + +#if USE_POLL + if(count) + { + fd.events |= POLLOUT; + ++c->out.writing; + } +#else + FD_ZERO(&wfds); + if(count) + { + FD_SET(c->fd, &wfds); + ++c->out.writing; + } +#endif + + pthread_mutex_unlock(&c->iolock); + do { +#if USE_POLL + ret = poll(&fd, 1, -1); + /* If poll() returns an event we didn't expect, such as POLLNVAL, treat + * it as if it failed. */ + if(ret >= 0 && (fd.revents & ~fd.events)) + { + ret = -1; + break; + } +#else + ret = select(c->fd + 1, &rfds, &wfds, 0, 0); +#endif + } while (ret == -1 && errno == EINTR); + if(ret < 0) + { + _xcb_conn_shutdown(c, XCB_CONN_ERROR); + ret = 0; + } + pthread_mutex_lock(&c->iolock); + + if(ret) + { +#if USE_POLL + if((fd.revents & POLLIN) == POLLIN) +#else + if(FD_ISSET(c->fd, &rfds)) +#endif + ret = ret && _xcb_in_read(c); + +#if USE_POLL + if((fd.revents & POLLOUT) == POLLOUT) +#else + if(FD_ISSET(c->fd, &wfds)) +#endif + ret = ret && write_vec(c, vector, count); + } + + if(count) + --c->out.writing; + --c->in.reading; + + return ret; +} diff --git a/libxcb/src/xcb_in.c b/libxcb/src/xcb_in.c index e075a4047..969cfc08b 100644 --- a/libxcb/src/xcb_in.c +++ b/libxcb/src/xcb_in.c @@ -174,7 +174,7 @@ static int read_packet(xcb_connection_t *c) (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t))); if(!buf) { - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT); return 0; } @@ -210,7 +210,7 @@ static int read_packet(xcb_connection_t *c) struct reply_list *cur = malloc(sizeof(struct reply_list)); if(!cur) { - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT); free(buf); return 0; } @@ -227,7 +227,7 @@ static int read_packet(xcb_connection_t *c) event = malloc(sizeof(struct event_list)); if(!event) { - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT); free(buf); return 0; } @@ -433,7 +433,7 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex pend = malloc(sizeof(*pend)); if(!pend) { - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT); return; } @@ -633,7 +633,7 @@ int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds assert(workaround != WORKAROUND_NONE || flags != 0); if(!pend) { - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT); return 0; } pend->first_request = pend->last_request = request; @@ -672,7 +672,7 @@ int _xcb_in_read(xcb_connection_t *c) if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK)) #endif /* !_WIN32 */ return 1; - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_ERROR); return 0; } @@ -691,7 +691,7 @@ int _xcb_in_read_block(xcb_connection_t *c, void *buf, int len) int ret = read_block(c->fd, (char *) buf + done, len - done); if(ret <= 0) { - _xcb_conn_shutdown(c); + _xcb_conn_shutdown(c, XCB_CONN_ERROR); return ret; } } diff --git a/libxcb/src/xcb_out.c b/libxcb/src/xcb_out.c index 4f27de116..c0601f270 100644 --- a/libxcb/src/xcb_out.c +++ b/libxcb/src/xcb_out.c @@ -1,372 +1,378 @@ -/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp. - * - * 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 - * AUTHORS 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 names of the authors or their - * institutions 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 authors. - */ - -/* Stuff that sends stuff to the server. */ - -#include -#include -#include -#include - -#include "xcb.h" -#include "xcbext.h" -#include "xcbint.h" -#include "bigreq.h" - -static inline void send_request(xcb_connection_t *c, int isvoid, enum workarounds workaround, int flags, struct iovec *vector, int count) -{ - if(c->has_error) - return; - - ++c->out.request; - if(!isvoid) - c->in.request_expected = c->out.request; - if(workaround != WORKAROUND_NONE || flags != 0) - _xcb_in_expect_reply(c, c->out.request, workaround, flags); - - while(count && c->out.queue_len + vector[0].iov_len <= sizeof(c->out.queue)) - { - memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len); - c->out.queue_len += vector[0].iov_len; - vector[0].iov_base = (char *) vector[0].iov_base + vector[0].iov_len; - vector[0].iov_len = 0; - ++vector, --count; - } - if(!count) - return; - - --vector, ++count; - vector[0].iov_base = c->out.queue; - vector[0].iov_len = c->out.queue_len; - c->out.queue_len = 0; - _xcb_out_send(c, vector, count); -} - -static void send_sync(xcb_connection_t *c) -{ - static const union { - struct { - uint8_t major; - uint8_t pad; - uint16_t len; - } fields; - uint32_t packet; - } sync_req = { { /* GetInputFocus */ 43, 0, 1 } }; - struct iovec vector[2]; - vector[1].iov_base = (char *) &sync_req; - vector[1].iov_len = sizeof(sync_req); - send_request(c, 0, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY, vector + 1, 1); -} - -static void get_socket_back(xcb_connection_t *c) -{ - while(c->out.return_socket && c->out.socket_moving) - pthread_cond_wait(&c->out.socket_cond, &c->iolock); - if(!c->out.return_socket) - return; - - c->out.socket_moving = 1; - pthread_mutex_unlock(&c->iolock); - c->out.return_socket(c->out.socket_closure); - pthread_mutex_lock(&c->iolock); - c->out.socket_moving = 0; - - pthread_cond_broadcast(&c->out.socket_cond); - c->out.return_socket = 0; - c->out.socket_closure = 0; - _xcb_in_replies_done(c); -} - -/* Public interface */ - -void xcb_prefetch_maximum_request_length(xcb_connection_t *c) -{ - if(c->has_error) - return; - pthread_mutex_lock(&c->out.reqlenlock); - if(c->out.maximum_request_length_tag == LAZY_NONE) - { - const xcb_query_extension_reply_t *ext; - ext = xcb_get_extension_data(c, &xcb_big_requests_id); - if(ext && ext->present) - { - c->out.maximum_request_length_tag = LAZY_COOKIE; - c->out.maximum_request_length.cookie = xcb_big_requests_enable(c); - } - else - { - c->out.maximum_request_length_tag = LAZY_FORCED; - c->out.maximum_request_length.value = c->setup->maximum_request_length; - } - } - pthread_mutex_unlock(&c->out.reqlenlock); -} - -uint32_t xcb_get_maximum_request_length(xcb_connection_t *c) -{ - if(c->has_error) - return 0; - xcb_prefetch_maximum_request_length(c); - pthread_mutex_lock(&c->out.reqlenlock); - if(c->out.maximum_request_length_tag == LAZY_COOKIE) - { - xcb_big_requests_enable_reply_t *r = xcb_big_requests_enable_reply(c, c->out.maximum_request_length.cookie, 0); - c->out.maximum_request_length_tag = LAZY_FORCED; - if(r) - { - c->out.maximum_request_length.value = r->maximum_request_length; - free(r); - } - else - c->out.maximum_request_length.value = c->setup->maximum_request_length; - } - pthread_mutex_unlock(&c->out.reqlenlock); - return c->out.maximum_request_length.value; -} - -unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req) -{ - uint64_t request; - uint32_t prefix[2]; - int veclen = req->count; - enum workarounds workaround = WORKAROUND_NONE; - - if(c->has_error) - return 0; - - assert(c != 0); - assert(vector != 0); - assert(req->count > 0); - - if(!(flags & XCB_REQUEST_RAW)) - { - static const char pad[3]; - unsigned int i; - uint16_t shortlen = 0; - size_t longlen = 0; - assert(vector[0].iov_len >= 4); - /* set the major opcode, and the minor opcode for extensions */ - if(req->ext) - { - const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext); - if(!(extension && extension->present)) - { - _xcb_conn_shutdown(c); - return 0; - } - ((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode; - ((uint8_t *) vector[0].iov_base)[1] = req->opcode; - } - else - ((uint8_t *) vector[0].iov_base)[0] = req->opcode; - - /* put together the length field, possibly using BIGREQUESTS */ - for(i = 0; i < req->count; ++i) - { - longlen += vector[i].iov_len; - if(!vector[i].iov_base) - { - vector[i].iov_base = (char *) pad; - assert(vector[i].iov_len <= sizeof(pad)); - } - } - assert((longlen & 3) == 0); - longlen >>= 2; - - if(longlen <= c->setup->maximum_request_length) - { - /* we don't need BIGREQUESTS. */ - shortlen = longlen; - longlen = 0; - } - else if(longlen > xcb_get_maximum_request_length(c)) - { - _xcb_conn_shutdown(c); - return 0; /* server can't take this; maybe need BIGREQUESTS? */ - } - - /* set the length field. */ - ((uint16_t *) vector[0].iov_base)[1] = shortlen; - if(!shortlen) - { - prefix[0] = ((uint32_t *) vector[0].iov_base)[0]; - prefix[1] = ++longlen; - vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1; - vector[0].iov_len -= sizeof(uint32_t); - --vector, ++veclen; - vector[0].iov_base = prefix; - vector[0].iov_len = sizeof(prefix); - } - } - flags &= ~XCB_REQUEST_RAW; - - /* do we need to work around the X server bug described in glx.xml? */ - /* XXX: GetFBConfigs won't use BIG-REQUESTS in any sane - * configuration, but that should be handled here anyway. */ - if(req->ext && !req->isvoid && !strcmp(req->ext->name, "GLX") && - ((req->opcode == 17 && ((uint32_t *) vector[0].iov_base)[1] == 0x10004) || - req->opcode == 21)) - workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG; - - /* get a sequence number and arrange for delivery. */ - pthread_mutex_lock(&c->iolock); - /* wait for other writing threads to get out of my way. */ - while(c->out.writing) - pthread_cond_wait(&c->out.cond, &c->iolock); - get_socket_back(c); - - /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without - * a reply. */ - if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) - send_sync(c); - /* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having - * applications see sequence 0 as that is used to indicate - * an error in sending the request */ - if((unsigned int) (c->out.request + 1) == 0) - send_sync(c); - - /* The above send_sync calls could drop the I/O lock, but this - * thread will still exclude any other thread that tries to write, - * so the sequence number postconditions still hold. */ - send_request(c, req->isvoid, workaround, flags, vector, veclen); - request = c->has_error ? 0 : c->out.request; - pthread_mutex_unlock(&c->iolock); - return request; -} - -int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent) -{ - int ret; - if(c->has_error) - return 0; - pthread_mutex_lock(&c->iolock); - get_socket_back(c); - ret = _xcb_out_flush_to(c, c->out.request); - if(ret) - { - c->out.return_socket = return_socket; - c->out.socket_closure = closure; - if(flags) - _xcb_in_expect_reply(c, c->out.request, WORKAROUND_EXTERNAL_SOCKET_OWNER, flags); - assert(c->out.request == c->out.request_written); - *sent = c->out.request; - } - pthread_mutex_unlock(&c->iolock); - return ret; -} - -int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests) -{ - int ret; - if(c->has_error) - return 0; - pthread_mutex_lock(&c->iolock); - c->out.request += requests; - ret = _xcb_out_send(c, vector, count); - pthread_mutex_unlock(&c->iolock); - return ret; -} - -int xcb_flush(xcb_connection_t *c) -{ - int ret; - if(c->has_error) - return 0; - pthread_mutex_lock(&c->iolock); - ret = _xcb_out_flush_to(c, c->out.request); - pthread_mutex_unlock(&c->iolock); - return ret; -} - -/* Private interface */ - -int _xcb_out_init(_xcb_out *out) -{ - if(pthread_cond_init(&out->socket_cond, 0)) - return 0; - out->return_socket = 0; - out->socket_closure = 0; - out->socket_moving = 0; - - if(pthread_cond_init(&out->cond, 0)) - return 0; - out->writing = 0; - - out->queue_len = 0; - - out->request = 0; - out->request_written = 0; - - if(pthread_mutex_init(&out->reqlenlock, 0)) - return 0; - out->maximum_request_length_tag = LAZY_NONE; - - return 1; -} - -void _xcb_out_destroy(_xcb_out *out) -{ - pthread_cond_destroy(&out->cond); - pthread_mutex_destroy(&out->reqlenlock); -} - -int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count) -{ - int ret = 1; - while(ret && count) - ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count); - c->out.request_written = c->out.request; - pthread_cond_broadcast(&c->out.cond); - _xcb_in_wake_up_next_reader(c); - return ret; -} - -void _xcb_out_send_sync(xcb_connection_t *c) -{ - /* wait for other writing threads to get out of my way. */ - while(c->out.writing) - pthread_cond_wait(&c->out.cond, &c->iolock); - get_socket_back(c); - send_sync(c); -} - -int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request) -{ - assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request)); - if(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request)) - return 1; - if(c->out.queue_len) - { - struct iovec vec; - vec.iov_base = c->out.queue; - vec.iov_len = c->out.queue_len; - c->out.queue_len = 0; - return _xcb_out_send(c, &vec, 1); - } - while(c->out.writing) - pthread_cond_wait(&c->out.cond, &c->iolock); - assert(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request)); - return 1; -} +/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp. + * + * 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 + * AUTHORS 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 names of the authors or their + * institutions 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 authors. + */ + +/* Stuff that sends stuff to the server. */ + +#include +#include +#include +#include + +#include "xcb.h" +#include "xcbext.h" +#include "xcbint.h" +#include "bigreq.h" + +static inline void send_request(xcb_connection_t *c, int isvoid, enum workarounds workaround, int flags, struct iovec *vector, int count) +{ + if(c->has_error) + return; + + ++c->out.request; + if(!isvoid) + c->in.request_expected = c->out.request; + if(workaround != WORKAROUND_NONE || flags != 0) + _xcb_in_expect_reply(c, c->out.request, workaround, flags); + + while(count && c->out.queue_len + vector[0].iov_len <= sizeof(c->out.queue)) + { + memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len); + c->out.queue_len += vector[0].iov_len; + vector[0].iov_base = (char *) vector[0].iov_base + vector[0].iov_len; + vector[0].iov_len = 0; + ++vector, --count; + } + if(!count) + return; + + --vector, ++count; + vector[0].iov_base = c->out.queue; + vector[0].iov_len = c->out.queue_len; + c->out.queue_len = 0; + _xcb_out_send(c, vector, count); +} + +static void send_sync(xcb_connection_t *c) +{ + static const union { + struct { + uint8_t major; + uint8_t pad; + uint16_t len; + } fields; + uint32_t packet; + } sync_req = { { /* GetInputFocus */ 43, 0, 1 } }; + struct iovec vector[2]; + vector[1].iov_base = (char *) &sync_req; + vector[1].iov_len = sizeof(sync_req); + send_request(c, 0, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY, vector + 1, 1); +} + +static void get_socket_back(xcb_connection_t *c) +{ + while(c->out.return_socket && c->out.socket_moving) + pthread_cond_wait(&c->out.socket_cond, &c->iolock); + if(!c->out.return_socket) + return; + + c->out.socket_moving = 1; + pthread_mutex_unlock(&c->iolock); + c->out.return_socket(c->out.socket_closure); + pthread_mutex_lock(&c->iolock); + c->out.socket_moving = 0; + + pthread_cond_broadcast(&c->out.socket_cond); + c->out.return_socket = 0; + c->out.socket_closure = 0; + _xcb_in_replies_done(c); +} + +/* Public interface */ + +void xcb_prefetch_maximum_request_length(xcb_connection_t *c) +{ + if(c->has_error) + return; + pthread_mutex_lock(&c->out.reqlenlock); + if(c->out.maximum_request_length_tag == LAZY_NONE) + { + const xcb_query_extension_reply_t *ext; + ext = xcb_get_extension_data(c, &xcb_big_requests_id); + if(ext && ext->present) + { + c->out.maximum_request_length_tag = LAZY_COOKIE; + c->out.maximum_request_length.cookie = xcb_big_requests_enable(c); + } + else + { + c->out.maximum_request_length_tag = LAZY_FORCED; + c->out.maximum_request_length.value = c->setup->maximum_request_length; + } + } + pthread_mutex_unlock(&c->out.reqlenlock); +} + +uint32_t xcb_get_maximum_request_length(xcb_connection_t *c) +{ + if(c->has_error) + return 0; + xcb_prefetch_maximum_request_length(c); + pthread_mutex_lock(&c->out.reqlenlock); + if(c->out.maximum_request_length_tag == LAZY_COOKIE) + { + xcb_big_requests_enable_reply_t *r = xcb_big_requests_enable_reply(c, c->out.maximum_request_length.cookie, 0); + c->out.maximum_request_length_tag = LAZY_FORCED; + if(r) + { + c->out.maximum_request_length.value = r->maximum_request_length; + free(r); + } + else + c->out.maximum_request_length.value = c->setup->maximum_request_length; + } + pthread_mutex_unlock(&c->out.reqlenlock); + return c->out.maximum_request_length.value; +} + +unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req) +{ + uint64_t request; + uint32_t prefix[2]; + int veclen = req->count; + enum workarounds workaround = WORKAROUND_NONE; + + if(c->has_error) + return 0; + + assert(c != 0); + assert(vector != 0); + assert(req->count > 0); + + if(!(flags & XCB_REQUEST_RAW)) + { + static const char pad[3]; + unsigned int i; + uint16_t shortlen = 0; + size_t longlen = 0; + assert(vector[0].iov_len >= 4); + /* set the major opcode, and the minor opcode for extensions */ + if(req->ext) + { + const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext); + if(!(extension && extension->present)) + { + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED); + return 0; + } + ((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode; + ((uint8_t *) vector[0].iov_base)[1] = req->opcode; + } + else + ((uint8_t *) vector[0].iov_base)[0] = req->opcode; + + /* put together the length field, possibly using BIGREQUESTS */ + for(i = 0; i < req->count; ++i) + { + longlen += vector[i].iov_len; + if(!vector[i].iov_base) + { + vector[i].iov_base = (char *) pad; + assert(vector[i].iov_len <= sizeof(pad)); + } + } + assert((longlen & 3) == 0); + longlen >>= 2; + + if(longlen <= c->setup->maximum_request_length) + { + /* we don't need BIGREQUESTS. */ + shortlen = longlen; + longlen = 0; + } + else if(longlen > xcb_get_maximum_request_length(c)) + { + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_REQ_LEN_EXCEED); + return 0; /* server can't take this; maybe need BIGREQUESTS? */ + } + + /* set the length field. */ + ((uint16_t *) vector[0].iov_base)[1] = shortlen; + if(!shortlen) + { + prefix[0] = ((uint32_t *) vector[0].iov_base)[0]; + prefix[1] = ++longlen; + vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1; + vector[0].iov_len -= sizeof(uint32_t); + --vector, ++veclen; + vector[0].iov_base = prefix; + vector[0].iov_len = sizeof(prefix); + } + } + flags &= ~XCB_REQUEST_RAW; + + /* do we need to work around the X server bug described in glx.xml? */ + /* XXX: GetFBConfigs won't use BIG-REQUESTS in any sane + * configuration, but that should be handled here anyway. */ + if(req->ext && !req->isvoid && !strcmp(req->ext->name, "GLX") && + ((req->opcode == 17 && ((uint32_t *) vector[0].iov_base)[1] == 0x10004) || + req->opcode == 21)) + workaround = WORKAROUND_GLX_GET_FB_CONFIGS_BUG; + + /* get a sequence number and arrange for delivery. */ + pthread_mutex_lock(&c->iolock); + /* wait for other writing threads to get out of my way. */ + while(c->out.writing) + pthread_cond_wait(&c->out.cond, &c->iolock); + get_socket_back(c); + + /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without + * a reply. */ + if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) + send_sync(c); + /* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having + * applications see sequence 0 as that is used to indicate + * an error in sending the request */ + if((unsigned int) (c->out.request + 1) == 0) + send_sync(c); + + /* The above send_sync calls could drop the I/O lock, but this + * thread will still exclude any other thread that tries to write, + * so the sequence number postconditions still hold. */ + send_request(c, req->isvoid, workaround, flags, vector, veclen); + request = c->has_error ? 0 : c->out.request; + pthread_mutex_unlock(&c->iolock); + return request; +} + +int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent) +{ + int ret; + if(c->has_error) + return 0; + pthread_mutex_lock(&c->iolock); + get_socket_back(c); + + /* _xcb_out_flush may drop the iolock allowing other threads to + * write requests, so keep flushing until we're done + */ + do + ret = _xcb_out_flush_to(c, c->out.request); + while (ret && c->out.request != c->out.request_written); + if(ret) + { + c->out.return_socket = return_socket; + c->out.socket_closure = closure; + if(flags) + _xcb_in_expect_reply(c, c->out.request, WORKAROUND_EXTERNAL_SOCKET_OWNER, flags); + assert(c->out.request == c->out.request_written); + *sent = c->out.request; + } + pthread_mutex_unlock(&c->iolock); + return ret; +} + +int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests) +{ + int ret; + if(c->has_error) + return 0; + pthread_mutex_lock(&c->iolock); + c->out.request += requests; + ret = _xcb_out_send(c, vector, count); + pthread_mutex_unlock(&c->iolock); + return ret; +} + +int xcb_flush(xcb_connection_t *c) +{ + int ret; + if(c->has_error) + return 0; + pthread_mutex_lock(&c->iolock); + ret = _xcb_out_flush_to(c, c->out.request); + pthread_mutex_unlock(&c->iolock); + return ret; +} + +/* Private interface */ + +int _xcb_out_init(_xcb_out *out) +{ + if(pthread_cond_init(&out->socket_cond, 0)) + return 0; + out->return_socket = 0; + out->socket_closure = 0; + out->socket_moving = 0; + + if(pthread_cond_init(&out->cond, 0)) + return 0; + out->writing = 0; + + out->queue_len = 0; + + out->request = 0; + out->request_written = 0; + + if(pthread_mutex_init(&out->reqlenlock, 0)) + return 0; + out->maximum_request_length_tag = LAZY_NONE; + + return 1; +} + +void _xcb_out_destroy(_xcb_out *out) +{ + pthread_cond_destroy(&out->cond); + pthread_mutex_destroy(&out->reqlenlock); +} + +int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count) +{ + int ret = 1; + while(ret && count) + ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count); + c->out.request_written = c->out.request; + pthread_cond_broadcast(&c->out.cond); + _xcb_in_wake_up_next_reader(c); + return ret; +} + +void _xcb_out_send_sync(xcb_connection_t *c) +{ + /* wait for other writing threads to get out of my way. */ + while(c->out.writing) + pthread_cond_wait(&c->out.cond, &c->iolock); + get_socket_back(c); + send_sync(c); +} + +int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request) +{ + assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request)); + if(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request)) + return 1; + if(c->out.queue_len) + { + struct iovec vec; + vec.iov_base = c->out.queue; + vec.iov_len = c->out.queue_len; + c->out.queue_len = 0; + return _xcb_out_send(c, &vec, 1); + } + while(c->out.writing) + pthread_cond_wait(&c->out.cond, &c->iolock); + assert(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request)); + return 1; +} diff --git a/libxcb/src/xcb_util.c b/libxcb/src/xcb_util.c index fcb11f042..9329b81dd 100644 --- a/libxcb/src/xcb_util.c +++ b/libxcb/src/xcb_util.c @@ -34,11 +34,11 @@ #include #include #include -#include #ifdef _WIN32 #include "xcb_windefs.h" #else +#include #include #include #include @@ -424,13 +424,24 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname, int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp); if(!parsed) { - c = (xcb_connection_t *) &error_connection; + c = _xcb_conn_ret_error(XCB_CONN_CLOSED_PARSE_ERR); goto out; - } else + } else { +#ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + c = (xcb_connection_t *) &error_connection; + goto out; + } +#endif fd = _xcb_open(host, protocol, display); + } if(fd == -1) { - c = (xcb_connection_t *) &error_connection; + c = _xcb_conn_ret_error(XCB_CONN_ERROR); +#ifdef _WIN32 + WSACleanup(); +#endif goto out; } diff --git a/libxcb/src/xcbint.h b/libxcb/src/xcbint.h index 096576c4a..f9e5a52f7 100644 --- a/libxcb/src/xcbint.h +++ b/libxcb/src/xcbint.h @@ -174,8 +174,6 @@ void _xcb_ext_destroy(xcb_connection_t *c); /* xcb_conn.c */ -extern const int error_connection; - struct xcb_connection_t { int has_error; @@ -193,7 +191,10 @@ struct xcb_connection_t { _xcb_xid xid; }; -void _xcb_conn_shutdown(xcb_connection_t *c); +void _xcb_conn_shutdown(xcb_connection_t *c, int err); + +xcb_connection_t *_xcb_conn_ret_error(int err); + int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count); diff --git a/libxcb/xcb-proto/NEWS b/libxcb/xcb-proto/NEWS index e6028d602..32bcc6924 100644 --- a/libxcb/xcb-proto/NEWS +++ b/libxcb/xcb-proto/NEWS @@ -1,5 +1,37 @@ +Release 1.7 (2012-01-11) +======================== +* Add missing padding bytes to ChangeKeyboardMapping request +* Corrected type of FakeInput rootX & rootY fields +* Changed Exception message in case of unknown/unhandled XML tags +* xcbgen: perform lenfield lookup within all anchestors +* Add support for new expr tags popcount, enumref, sumof +* Changed handling of anchestor types +* Assign switch name to bitcases +* Support name attribute for bitcases and set BitcaseType.has_name accordingly +* Use absolute imports in xcbgen for Python 3 compatibilit +* dri2: Update to version 1.3 (v2) +* glx: Replace some 'reserved' fields with explicit padding +* glx: Use glx:CONTEXT for share_list parameter of CreateNewContext +* glx: Use FBCONFIG type for fbconfig parameter of CreateNewContext and CreatePixmap +* glx: Add protocol for GLX_ARB_create_context and GLX_ARB_create_context_profile +* Add support for fence sync objects +* xf86dri: fix GetDrawableInfo reply +* xproto: fix TranslateCoordinates reply +* xcbgen: Add unop support +* xf86vidmode: Fix padding expressions +* dri2: Add proper padding before driver_name +* Add libdir/exec_prefix to xcb-xproto.pc +* Revive support for hex literals in protocol +* Add description of new protocol elements +* Add XKEYBOARD protocol description +* Fix ChangeHosts address string +* Fix SetFontPath path string encoding +* Fix some fields name +* Fix XKB GetState missing lookupMods field +* Add RENDER 0.11 definitions + Release 1.6 (2009-12-02) -======================= +======================== * Add DRI2 protocol, based off of dri2proto.h and the server code. (v2) * xf86dri.xml seems to have been wrong forever. Fixes bug #16894. * shape: add missing padding bytes to GetRectangles diff --git a/libxcb/xcb-proto/configure.ac b/libxcb/xcb-proto/configure.ac index 1a6ca0152..5368e2a05 100644 --- a/libxcb/xcb-proto/configure.ac +++ b/libxcb/xcb-proto/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.57) AC_INIT([XCB Proto], - 1.6, + 1.7, [xcb@lists.freedesktop.org]) AC_CONFIG_SRCDIR([xcb-proto.pc.in]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) diff --git a/libxcb/xcb-proto/src/xkb.xml b/libxcb/xcb-proto/src/xkb.xml index f738378f5..e8f4c021d 100644 --- a/libxcb/xcb-proto/src/xkb.xml +++ b/libxcb/xcb-proto/src/xkb.xml @@ -1,2774 +1,2775 @@ - - - - - xproto - - - - 255 - - 32 - - - 4 - - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - - - - 0 - 1 - 2 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - - - - 0 - 1 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - - - - - 27 - 28 - 29 - 30 - 31 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - - - - 6 - 7 - - - - - - - - - - - 0 - 4 - - - - 768 - 1280 - - - - - 0 - 5 - - - - 768 - - - - - 256 - 512 - 768 - 1024 - 1280 - 1536 - 65280 - - - - - 0 - 1 - 2 - 3 - - - - 254 - 255 - - - - 0 - 1 - 2 - 3 - - - - 7 - - - - 0 - 6 - 7 - - - - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 - - - - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 - - - - 15 - 14 - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 - - - - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 - - - - 0 - 1 - 2 - 3 - 4 - - - - 7 - 127 - - - - 7 - 6 - 5 - - - - 4 - 3 - 2 - 1 - 0 - - - - 4 - 3 - 2 - 1 - 0 - - - - - - - - - - - - - - - 0 - 1 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - - - - 0 - 1 - 2 - 3 - 4 - - - - 0 - 1 - 2 - 3 - 4 - - - - - - - - - - - 4 - - - - - - 4 - - - 4 - - - - - - - length - - - - - - - length - - - - - - - - - - - - - - - - - - - - - - - - nMapEntries - - - - hasPreserve - nMapEntries - - - - - - - 4 - - - - - - nSyms - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 1 - 2 - 3 - 4 - 129 - 130 - 131 - 132 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nMapEntries - - - - preserve - nMapEntries - - - - - - - - - - nameLength - - - - valueLength - - - - - - - - - nPoints - - - - - - - - - - - nOutlines - - - - - - 4 - - - - - - - - - 4 - - - 4 - - - - - - - - - nKeys - - - - - - - - - nRows - - - - - - - - - - - nKeys - - - - - 1 - 2 - 3 - 4 - 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nRows - - - nDoodads - - - nOverlays - - - - - - - - length - - - - - - - - - - - - - namesPresent - - - - - mapsPresent - - - - - - - - 255 - 254 - 253 - - - - - - - - - - - - - 0 - 1 - 2 - 2 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 1 - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - 0 - 1 - 2 - 2 - 3 - - - - 3 - 4 - 5 - 6 - - - - - - - - - - - - - - - - - - - - 0 - 2 - - - - - - - - - - - 0 - 1 - 2 - 3 - 4 - - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - - - - - - - - - - - - - - 0 - 1 - 2 - - - - - - - 6 - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 1 - - - - - - - - - - - - 0 - 1 - 2 - 3 - 4 - 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - affectWhich - - clear - selectAll - - - - NewKeyboardNotify - - - - - StateNotify - - - - - ControlsNotify - - - - - IndicatorStateNotify - - - - - IndicatorMapNotify - - - - - NamesNotify - - - - - CompatMapNotify - - - - - BellNotify - - - - - ActionMessage - - - - - AccessXNotify - - - - - ExtensionDeviceNotify - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - present - - KeyTypes - - nTypes - - - - KeySyms - - nKeySyms - - - - KeyActions - - nKeyActions - - - totalActions - - - - KeyBehaviors - - totalKeyBehaviors - - - - VirtualMods - - nVModMapKeys - - - - ExplicitComponents - - totalKeyExplicit - - - - ModifierMap - - totalModMapKeys - - - - VirtualModMap - - totalVModMapKeys - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - present - - KeyTypes - - nTypes - - - - KeySyms - - nKeySyms - - - - KeyActions - - nKeyActions - - - totalActions - - - - KeyBehaviors - - totalKeyBehaviors - - - - VirtualMods - - nVModMapKeys - - - - ExplicitComponents - - totalKeyExplicit - - - - ModifierMap - - totalModMapKeys - - - - VirtualModMap - - totalVModMapKeys - - - - - - - - - - - - - - - - - - - - - - 16 - nSIRtrn - - - - - groupsRtrn - - - - - - - - - - - - - - - - - 16 - nSI - - - - - groups - - - - - - - - - - - - - - - - - - - - - - - - - - nIndicators - - - - - - - - - - - which - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - which - - Keycodes - - - - Geometry - - - - Symbols - - - - PhysSymbols - - - - Types - - - - Compat - - - - KeyTypeNames - - nTypes - - - - KTLevelNames - - - nTypes - - - - - - - IndicatorNames - - - indicators - - - - - VirtualModNames - - - virtualMods - - - - - GroupNames - - - groupNames - - - - - KeyNames - - nKeys - - - - KeyAliases - - nKeyAliases - - - - RGNames - - nRadioGroups - - - - - - - - - - - - - - - - - - - - - - - - which - - Keycodes - - - - Geometry - - - - Symbols - - - - PhysSymbols - - - - Types - - - - Compat - - - - KeyTypeNames - - nTypes - - - - KTLevelNames - - nKTLevels - - - - - - - IndicatorNames - - - indicators - - - - - VirtualModNames - - - virtualMods - - - - - GroupNames - - - groupNames - - - - - KeyNames - - nKeys - - - - KeyAliases - - nKeyAliases - - - - RGNames - - nRadioGroups - - - - - - - - - - - - - - - - - - - - - - - - - - - nProperties - - - nColors - - - nShapes - - - nSections - - - nDoodads - - - nKeyAliases - - - - - - - - - - - - - - - - - - - - - nProperties - - - nColors - - - nShapes - - - nSections - - - nDoodads - - - nKeyAliases - - - - - - - - - - - - - - - - - - - - - - - - - - - keymapsSpecLen - - - - keycodesSpecLen - - - - typesSpecLen - - - - compatMapSpecLen - - - - symbolsSpecLen - - - - geometrySpecLen - - - - - - - - - - - - - nKeymaps - - - nKeycodes - - - nTypes - - - nCompatMaps - - - nSymbols - - - nGeometries - - - - - - - - - - - - - keymapsSpecLen - - - - keycodesSpecLen - - - - typesSpecLen - - - - compatMapSpecLen - - - - symbolsSpecLen - - - - geometrySpecLen - - - - - - - - - - - - reported - - Types - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - present - - KeyTypes - - nTypes - - - - KeySyms - - nKeySyms - - - - KeyActions - - nKeyActions - - - totalActions - - - - KeyBehaviors - - totalKeyBehaviors - - - - VirtualMods - - nVModMapKeys - - - - ExplicitComponents - - totalKeyExplicit - - - - ModifierMap - - totalModMapKeys - - - - VirtualModMap - - totalVModMapKeys - - - - - - CompatMap - - - - - - - - - - 16 - nSIRtrn - - - - - groupsRtrn - - - - - ClientSymbols - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - present - - KeyTypes - - nTypes - - - - KeySyms - - nKeySyms - - - - KeyActions - - nKeyActions - - - totalActions - - - - KeyBehaviors - - totalKeyBehaviors - - - - VirtualMods - - nVModMapKeys - - - - ExplicitComponents - - totalKeyExplicit - - - - ModifierMap - - totalModMapKeys - - - - VirtualModMap - - totalVModMapKeys - - - - - - ServerSymbols - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - present - - KeyTypes - - nTypes - - - - KeySyms - - nKeySyms - - - - KeyActions - - nKeyActions - - - totalActions - - - - KeyBehaviors - - totalKeyBehaviors - - - - VirtualMods - - nVModMapKeys - - - - ExplicitComponents - - totalKeyExplicit - - - - ModifierMap - - totalModMapKeys - - - - VirtualModMap - - totalVModMapKeys - - - - - - IndicatorMaps - - - - - - - nIndicators - - - - KeyNames - - - - - - - - - - - - - - - - which - - Keycodes - - - - Geometry - - - - Symbols - - - - PhysSymbols - - - - Types - - - - Compat - - - - KeyTypeNames - - nTypes - - - - KTLevelNames - - nKTLevels - - - - - - - IndicatorNames - - - indicators - - - - - VirtualModNames - - - virtualMods - - - - - GroupNames - - - groupNames - - - - - KeyNames - - nKeys - - - - KeyAliases - - nKeyAliases - - - - RGNames - - nRadioGroups - - - - - - OtherNames - - - - - - - - - - - - - - - - which - - Keycodes - - - - Geometry - - - - Symbols - - - - PhysSymbols - - - - Types - - - - Compat - - - - KeyTypeNames - - nTypes - - - - KTLevelNames - - nKTLevels - - - - - - - IndicatorNames - - - indicators - - - - - VirtualModNames - - - virtualMods - - - - - GroupNames - - - groupNames - - - - - KeyNames - - nKeys - - - - KeyAliases - - nKeyAliases - - - - RGNames - - nRadioGroups - - - - - - Geometry - - - - - - - - - - - - - - - - - nProperties - - - nColors - - - nShapes - - - nSections - - - nDoodads - - - nKeyAliases - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nameLen - - - nBtnsRtrn - - - nDeviceLedFBs - - - - - - - - - - - - - nBtns - - - nDeviceLedFBs - - - - - - - - - - - - msgLength - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + xproto + + + + 255 + + 32 + + + 4 + + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + + + + 0 + 1 + 2 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + + + 0 + 1 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + + + + + 27 + 28 + 29 + 30 + 31 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + + + 6 + 7 + + + + + + + + + + + 0 + 4 + + + + 768 + 1280 + + + + + 0 + 5 + + + + 768 + + + + + 256 + 512 + 768 + 1024 + 1280 + 1536 + 65280 + + + + + 0 + 1 + 2 + 3 + + + + 254 + 255 + + + + 0 + 1 + 2 + 3 + + + + 7 + + + + 0 + 6 + 7 + + + + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + 0 + 1 + 2 + 3 + 4 + + + + 7 + 127 + + + + 7 + 6 + 5 + + + + 4 + 3 + 2 + 1 + 0 + + + + 4 + 3 + 2 + 1 + 0 + + + + + + + + + + + + + + + 0 + 1 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + + + 0 + 1 + 2 + 3 + 4 + + + + 0 + 1 + 2 + 3 + 4 + + + + + + + + + + + 4 + + + + + + 4 + + + 4 + + + + + + + length + + + + + + + length + + + + + + + + + + + + + + + + + + + + + + + + nMapEntries + + + + hasPreserve + nMapEntries + + + + + + + 4 + + + + + + nSyms + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + 3 + 4 + 129 + 130 + 131 + 132 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nMapEntries + + + + preserve + nMapEntries + + + + + + + + + + nameLength + + + + valueLength + + + + + + + + + nPoints + + + + + + + + + + + nOutlines + + + + + + 4 + + + + + + + + + 4 + + + 4 + + + + + + + + + nKeys + + + + + + + + + nRows + + + + + + + + + + + nKeys + + + + + 1 + 2 + 3 + 4 + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nRows + + + nDoodads + + + nOverlays + + + + + + + + length + + + + + + + + + + + + + namesPresent + + + + + mapsPresent + + + + + + + + 255 + 254 + 253 + + + + + + + + + + + + + 0 + 1 + 2 + 2 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 0 + + + + + + + + + + + + 0 + 1 + 2 + 2 + 3 + + + + 3 + 4 + 5 + 6 + + + + + + + + + + + + + + + + + + + + 0 + 2 + + + + + + + + + + + 0 + 1 + 2 + 3 + 4 + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + + + + + + + + + + + + + 0 + 1 + 2 + + + + + + + 6 + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + 0 + 1 + 2 + 3 + 4 + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + affectWhich + + clear + selectAll + + + + NewKeyboardNotify + + + + + StateNotify + + + + + ControlsNotify + + + + + IndicatorStateNotify + + + + + IndicatorMapNotify + + + + + NamesNotify + + + + + CompatMapNotify + + + + + BellNotify + + + + + ActionMessage + + + + + AccessXNotify + + + + + ExtensionDeviceNotify + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + present + + KeyTypes + + nTypes + + + + KeySyms + + nKeySyms + + + + KeyActions + + nKeyActions + + + totalActions + + + + KeyBehaviors + + totalKeyBehaviors + + + + VirtualMods + + nVModMapKeys + + + + ExplicitComponents + + totalKeyExplicit + + + + ModifierMap + + totalModMapKeys + + + + VirtualModMap + + totalVModMapKeys + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + present + + KeyTypes + + nTypes + + + + KeySyms + + nKeySyms + + + + KeyActions + + nKeyActions + + + totalActions + + + + KeyBehaviors + + totalKeyBehaviors + + + + VirtualMods + + nVModMapKeys + + + + ExplicitComponents + + totalKeyExplicit + + + + ModifierMap + + totalModMapKeys + + + + VirtualModMap + + totalVModMapKeys + + + + + + + + + + + + + + + + + + + + + + 16 + nSIRtrn + + + + + groupsRtrn + + + + + + + + + + + + + + + + + 16 + nSI + + + + + groups + + + + + + + + + + + + + + + + + + + + + + + + + + nIndicators + + + + + + + + + + + which + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + which + + Keycodes + + + + Geometry + + + + Symbols + + + + PhysSymbols + + + + Types + + + + Compat + + + + KeyTypeNames + + nTypes + + + + KTLevelNames + + + nTypes + + + + + + + IndicatorNames + + + indicators + + + + + VirtualModNames + + + virtualMods + + + + + GroupNames + + + groupNames + + + + + KeyNames + + nKeys + + + + KeyAliases + + nKeyAliases + + + + RGNames + + nRadioGroups + + + + + + + + + + + + + + + + + + + + + + + + which + + Keycodes + + + + Geometry + + + + Symbols + + + + PhysSymbols + + + + Types + + + + Compat + + + + KeyTypeNames + + nTypes + + + + KTLevelNames + + nKTLevels + + + + + + + IndicatorNames + + + indicators + + + + + VirtualModNames + + + virtualMods + + + + + GroupNames + + + groupNames + + + + + KeyNames + + nKeys + + + + KeyAliases + + nKeyAliases + + + + RGNames + + nRadioGroups + + + + + + + + + + + + + + + + + + + + + + + + + + + nProperties + + + nColors + + + nShapes + + + nSections + + + nDoodads + + + nKeyAliases + + + + + + + + + + + + + + + + + + + + + nProperties + + + nColors + + + nShapes + + + nSections + + + nDoodads + + + nKeyAliases + + + + + + + + + + + + + + + + + + + + + + + + + + + keymapsSpecLen + + + + keycodesSpecLen + + + + typesSpecLen + + + + compatMapSpecLen + + + + symbolsSpecLen + + + + geometrySpecLen + + + + + + + + + + + + + nKeymaps + + + nKeycodes + + + nTypes + + + nCompatMaps + + + nSymbols + + + nGeometries + + + + + + + + + + + + + keymapsSpecLen + + + + keycodesSpecLen + + + + typesSpecLen + + + + compatMapSpecLen + + + + symbolsSpecLen + + + + geometrySpecLen + + + + + + + + + + + + reported + + Types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + present + + KeyTypes + + nTypes + + + + KeySyms + + nKeySyms + + + + KeyActions + + nKeyActions + + + totalActions + + + + KeyBehaviors + + totalKeyBehaviors + + + + VirtualMods + + nVModMapKeys + + + + ExplicitComponents + + totalKeyExplicit + + + + ModifierMap + + totalModMapKeys + + + + VirtualModMap + + totalVModMapKeys + + + + + + CompatMap + + + + + + + + + + 16 + nSIRtrn + + + + + groupsRtrn + + + + + ClientSymbols + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + present + + KeyTypes + + nTypes + + + + KeySyms + + nKeySyms + + + + KeyActions + + nKeyActions + + + totalActions + + + + KeyBehaviors + + totalKeyBehaviors + + + + VirtualMods + + nVModMapKeys + + + + ExplicitComponents + + totalKeyExplicit + + + + ModifierMap + + totalModMapKeys + + + + VirtualModMap + + totalVModMapKeys + + + + + + ServerSymbols + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + present + + KeyTypes + + nTypes + + + + KeySyms + + nKeySyms + + + + KeyActions + + nKeyActions + + + totalActions + + + + KeyBehaviors + + totalKeyBehaviors + + + + VirtualMods + + nVModMapKeys + + + + ExplicitComponents + + totalKeyExplicit + + + + ModifierMap + + totalModMapKeys + + + + VirtualModMap + + totalVModMapKeys + + + + + + IndicatorMaps + + + + + + + nIndicators + + + + KeyNames + + + + + + + + + + + + + + + + which + + Keycodes + + + + Geometry + + + + Symbols + + + + PhysSymbols + + + + Types + + + + Compat + + + + KeyTypeNames + + nTypes + + + + KTLevelNames + + nKTLevels + + + + + + + IndicatorNames + + + indicators + + + + + VirtualModNames + + + virtualMods + + + + + GroupNames + + + groupNames + + + + + KeyNames + + nKeys + + + + KeyAliases + + nKeyAliases + + + + RGNames + + nRadioGroups + + + + + + OtherNames + + + + + + + + + + + + + + + + which + + Keycodes + + + + Geometry + + + + Symbols + + + + PhysSymbols + + + + Types + + + + Compat + + + + KeyTypeNames + + nTypes + + + + KTLevelNames + + nKTLevels + + + + + + + IndicatorNames + + + indicators + + + + + VirtualModNames + + + virtualMods + + + + + GroupNames + + + groupNames + + + + + KeyNames + + nKeys + + + + KeyAliases + + nKeyAliases + + + + RGNames + + nRadioGroups + + + + + + Geometry + + + + + + + + + + + + + + + + + nProperties + + + nColors + + + nShapes + + + nSections + + + nDoodads + + + nKeyAliases + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nameLen + + + nBtnsRtrn + + + nDeviceLedFBs + + + + + + + + + + + + + nBtns + + + nDeviceLedFBs + + + + + + + + + + + + msgLength + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libxcb/xcb-proto/src/xproto.xml b/libxcb/xcb-proto/src/xproto.xml index cbb5fa2db..42a6852a1 100644 --- a/libxcb/xcb-proto/src/xproto.xml +++ b/libxcb/xcb-proto/src/xproto.xml @@ -1482,7 +1482,10 @@ authorization from the authors. - + + + font_qty + @@ -2295,7 +2298,7 @@ authorization from the authors. - + address_len diff --git a/mesalib/Makefile b/mesalib/Makefile index 4a41948b5..1fa369a96 100644 --- a/mesalib/Makefile +++ b/mesalib/Makefile @@ -191,6 +191,8 @@ PACKAGE_NAME = MesaLib-$(PACKAGE_VERSION) EXTRA_FILES = \ aclocal.m4 \ configure \ + tests/Makefile.in \ + tests/glx/Makefile.in \ src/glsl/glsl_parser.cpp \ src/glsl/glsl_parser.h \ src/glsl/glsl_lexer.cpp \ diff --git a/mesalib/configs/linux-dri b/mesalib/configs/linux-dri index 6990c3a7a..e63790ea4 100644 --- a/mesalib/configs/linux-dri +++ b/mesalib/configs/linux-dri @@ -70,7 +70,6 @@ INTEL_CFLAGS = $(shell $(PKG_CONFIG) --cflags libdrm_intel) NOUVEAU_LIBS = $(shell $(PKG_CONFIG) --libs libdrm_nouveau) NOUVEAU_CFLAGS = $(shell $(PKG_CONFIG) --cflags libdrm_nouveau) -LIBDRM_RADEON_LIBS = $(shell $(PKG_CONFIG) --libs libdrm_radeon) -LIBDRM_RADEON_CFLAGS = $(shell $(PKG_CONFIG) --cflags libdrm_radeon) -RADEON_CFLAGS = "-DHAVE_LIBDRM_RADEON=1 $(LIBDRM_RADEON_CFLAGS)" +RADEON_LIBS = $(shell $(PKG_CONFIG) --libs libdrm_radeon) +RADEON_CFLAGS = $(shell $(PKG_CONFIG) --cflags libdrm_radeon) RADEON_LDFLAGS = $(LIBDRM_RADEON_LIBS) diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 511d147cb..7c50e3c00 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -38,8 +38,8 @@ AC_PROG_CC AC_PROG_CXX AC_CHECK_PROGS([MAKE], [gmake make]) AC_CHECK_PROGS([PYTHON2], [python2 python]) +AC_PROG_SED AC_PATH_PROG([MKDEP], [makedepend]) -AC_PATH_PROG([SED], [sed]) if test "x$MKDEP" = "x"; then AC_MSG_ERROR([makedepend is required to build Mesa]) @@ -70,7 +70,6 @@ AC_PATH_PROG([GTESTCONFIG], [gtest-config]) if test "x$GTESTCONFIG" != "x"; then GTEST_CFLAGS=`gtest-config --cppflags --cxxflags` GTEST_LIBS=`gtest-config --ldflags --libs` - HAVE_GTEST=1 AC_SUBST([GTEST_CFLAGS]) AC_SUBST([GTEST_LIBS]) HAVE_GTEST=yes @@ -663,7 +662,7 @@ AC_ARG_ENABLE([gallium_gbm], [enable_gallium_gbm=auto]) # Option for Gallium drivers -GALLIUM_DRIVERS_DEFAULT="r300,r600,swrast" +GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast" AC_ARG_WITH([gallium-drivers], [AS_HELP_STRING([--with-gallium-drivers@<:@=DIRS...@:>@], diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 0c67dce05..f677b7681 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -12,47 +12,45 @@ Feature Status GL 3.0: -GLSL 1.30 (GL_EXT_gpu_shader4, etc.) started +GLSL 1.30 DONE glBindFragDataLocation, glGetFragDataLocation DONE -Conditional rendering (GL_NV_conditional_render) DONE (swrast, softpipe, i965) -Map buffer subranges (GL_ARB_map_buffer_range) DONE -Clamping controls (GL_ARB_color_buffer_float) DONE -Float textures, renderbuffers (GL_ARB_texture_float) DONE (gallium r300) -GL_EXT_packed_float DONE (gallium r600) -GL_EXT_texture_shared_exponent DONE (gallium, swrast) -Float depth buffers (GL_ARB_depth_buffer_float) DONE -Framebuffer objects (GL_EXT_framebuffer_object) DONE +Conditional rendering (GL_NV_conditional_render) DONE (i965, r300, r600, swrast) +Map buffer subranges (GL_ARB_map_buffer_range) DONE (i965, r300, r600, swrast) +Clamping controls (GL_ARB_color_buffer_float) DONE (i965, r300, r600) +Float textures, renderbuffers (GL_ARB_texture_float) DONE (i965, r300, r600) +GL_EXT_packed_float DONE (i965, r600) +GL_EXT_texture_shared_exponent DONE (i965, r600, swrast) +Float depth buffers (GL_ARB_depth_buffer_float) DONE (i965, r600) +Framebuffer objects (GL_ARB_framebuffer_object) DONE (i965, r300, r600, swrast) Half-float DONE -Multisample blit DONE Non-normalized Integer texture/framebuffer formats ~50% done -1D/2D Texture arrays DONE (gallium, swrast) -Packed depth/stencil formats DONE -Per-buffer blend and masks (GL_EXT_draw_buffers2) DONE -GL_EXT_texture_compression_rgtc DONE (swrast, gallium r600) -Red and red/green texture formats DONE (swrast, i965, gallium) -Transform feedback (GL_EXT_transform_feedback) DONE -Vertex array objects (GL_APPLE_vertex_array_object) DONE -sRGB framebuffer format (GL_EXT_framebuffer_sRGB) core GL done (i965, gallium), GLX todo +1D/2D Texture arrays DONE +Per-buffer blend and masks (GL_EXT_draw_buffers2) DONE (i965, r600, swrast) +GL_EXT_texture_compression_rgtc DONE (i965, r300, r600, swrast) +Red and red/green texture formats DONE (i965, swrast, gallium) +Transform feedback (GL_EXT_transform_feedback) DONE (i965) +Vertex array objects (GL_APPLE_vertex_array_object) DONE (i965, r300, r600, swrast) +sRGB framebuffer format (GL_EXT_framebuffer_sRGB) DONE (i965, r600) glClearBuffer commands DONE glGetStringi command DONE glTexParameterI, glGetTexParameterI commands DONE -glVertexAttribI commands DONE (but converts int - values to floats) -Depth format cube textures not started -GLX_ARB_create_context (GLX 1.4 is required) not started +glVertexAttribI commands ~50% done (converts int + values to floats) +Depth format cube textures DONE +GLX_ARB_create_context (GLX 1.4 is required) DONE GL 3.1: GLSL 1.40 not started Instanced drawing (GL_ARB_draw_instanced) DONE (gallium, swrast) -Buffer copying (GL_ARB_copy_buffer) DONE -Primitive restart (GL_NV_primitive_restart) DONE (gallium) +Buffer copying (GL_ARB_copy_buffer) DONE (i965, r300, r600, swrast) +Primitive restart (GL_NV_primitive_restart) DONE (r600) 16 vertex texture image units DONE Texture buffer objs (GL_ARB_texture_buffer_object) not started -Rectangular textures (GL_ARB_texture_rectangle) DONE +Rectangular textures (GL_ARB_texture_rectangle) DONE (i965, r300, r600, swrast) Uniform buffer objs (GL_ARB_uniform_buffer_object) not started -Signed normalized textures (GL_EXT_texture_snorm) DONE (gallium) +Signed normalized textures (GL_EXT_texture_snorm) DONE (i965, r300, r600) GL 3.2: @@ -60,36 +58,36 @@ GL 3.2: Core/compatibility profiles not started GLSL 1.50 not started Geometry shaders (GL_ARB_geometry_shader4) partially done (Zack) -BGRA vertex order (GL_ARB_vertex_array_bgra) DONE -Base vertex offset(GL_ARB_draw_elements_base_vertex) DONE -Frag shader coord (GL_ARB_fragment_coord_conventions) DONE (swrast, gallium) -Provoking vertex (GL_ARB_provoking_vertex) DONE -Seamless cubemaps (GL_ARB_seamless_cube_map) DONE +BGRA vertex order (GL_ARB_vertex_array_bgra) DONE (i965, r300, r600, swrast) +Base vertex offset(GL_ARB_draw_elements_base_vertex) DONE (i965, r300, r600, swrast) +Frag shader coord (GL_ARB_fragment_coord_conventions) DONE (i965, r300, r600, swrast) +Provoking vertex (GL_ARB_provoking_vertex) DONE (i965, r300, r600, swrast) +Seamless cubemaps (GL_ARB_seamless_cube_map) DONE (i965, r600) Multisample textures (GL_ARB_texture_multisample) not started -Frag depth clamp (GL_ARB_depth_clamp) DONE -Fence objects (GL_ARB_sync) DONE -GLX_ARB_create_context_profile not started +Frag depth clamp (GL_ARB_depth_clamp) DONE (i965, r600, swrast) +Fence objects (GL_ARB_sync) DONE (i965, r300, r600, swrast) +GLX_ARB_create_context_profile DONE GL 3.3: GLSL 3.30 not started GL_ARB_blend_func_extended not started -GL_ARB_explicit_attrib_location DONE (swrast, i915, i965) -GL_ARB_occlusion_query2 DONE (swrast, gallium) -GL_ARB_sampler_objects DONE (gallium) -GL_ARB_texture_rgb10_a2ui DONE (gallium) -GL_ARB_texture_swizzle DONE (same as EXT version) +GL_ARB_explicit_attrib_location DONE (i915, i965, r300, r600, swrast) +GL_ARB_occlusion_query2 DONE (r300, r600, swrast) +GL_ARB_sampler_objects DONE (i965, r300, r600) +GL_ARB_texture_rgb10_a2ui DONE (r600) +GL_ARB_texture_swizzle DONE (same as EXT version) (i965, r300, r600, swrast) GL_ARB_timer_query ~60% done (the EXT variant) -GL_ARB_instanced_arrays DONE (gallium) -GL_ARB_vertex_type_2_10_10_10_rev DONE (gallium) +GL_ARB_instanced_arrays DONE (r300, r600) +GL_ARB_vertex_type_2_10_10_10_rev DONE (r600) GL 4.0: GLSL 4.0 not started GL_ARB_texture_query_lod not started -GL_ARB_draw_buffers_blend DONE (gallium softpipe) +GL_ARB_draw_buffers_blend DONE (r600, softpipe) GL_ARB_draw_indirect not started GL_ARB_gpu_shader_fp64 not started GL_ARB_sample_shading not started @@ -105,7 +103,7 @@ GL_ARB_transform_feedback3 not started GL 4.1: GLSL 4.1 not started -GL_ARB_ES2_compatibility DONE (i965) +GL_ARB_ES2_compatibility DONE (i965, r300, r600) GL_ARB_get_program_binary not started GL_ARB_separate_shader_objects some infrastructure done GL_ARB_shader_precision not started @@ -118,11 +116,11 @@ GLSL 4.2 not started GL_ARB_texture_compression_bptc not started GL_ARB_compressed_texture_pixel_storage not started GL_ARB_shader_atomic_counters not started -GL_ARB_texture_storage DONE (gallium, swrast) +GL_ARB_texture_storage DONE (r300, r600, swrast) GL_ARB_transform_feedback_instanced not started GL_ARB_base_instance not started GL_ARB_shader_image_load_store not started -GL_ARB_conservative_depth DONE (compiler) +GL_ARB_conservative_depth DONE (softpipe) GL_ARB_shading_language_420pack not started GL_ARB_internalformat_query not started GL_ARB_map_buffer_alignment not started diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h index 404bd21e1..f6196665f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.h +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -340,6 +340,9 @@ util_is_inf_or_nan(float x) * Find first bit set in word. Least significant bit is 1. * Return 0 if no bits set. */ +#ifndef FFS_DEFINED +#define FFS_DEFINED 1 + #if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); #pragma intrinsic(_BitScanForward) @@ -372,6 +375,8 @@ unsigned ffs( unsigned u ) #define ffs __builtin_ffs #endif +#endif /* FFS_DEFINED */ + /* Destructively loop over all of the bits in a mask as in: * diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 8587da0a3..d4385a644 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -127,6 +127,35 @@ glsl_type::contains_sampler() const } } +gl_texture_index +glsl_type::sampler_index() const +{ + const glsl_type *const t = (this->is_array()) ? this->fields.array : this; + + assert(t->is_sampler()); + + switch (t->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: + return (t->sampler_array) ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX; + case GLSL_SAMPLER_DIM_2D: + return (t->sampler_array) ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX; + case GLSL_SAMPLER_DIM_3D: + return TEXTURE_3D_INDEX; + case GLSL_SAMPLER_DIM_CUBE: + return TEXTURE_CUBE_INDEX; + case GLSL_SAMPLER_DIM_RECT: + return TEXTURE_RECT_INDEX; + case GLSL_SAMPLER_DIM_BUF: + assert(!"FINISHME: Implement ARB_texture_buffer_object"); + break; + case GLSL_SAMPLER_DIM_EXTERNAL: + return TEXTURE_EXTERNAL_INDEX; + default: + assert(!"Should not get here."); + break; + } +} + void glsl_type::generate_100ES_types(glsl_symbol_table *symtab) { diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 4ac90118b..2997c9311 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -28,6 +28,7 @@ #include #include +#include "main/mtypes.h" /* for gl_texture_index, C++'s enum rules are broken */ #ifdef __cplusplus extern "C" { @@ -353,6 +354,11 @@ struct glsl_type { */ bool contains_sampler() const; + /** + * Get the Mesa texture target index for a sampler type. + */ + gl_texture_index sampler_index() const; + /** * Query whether or not a type is an array */ diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index b331db705..02f57d911 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -209,7 +209,13 @@ public: union gl_constant_value *values) : map(map), uniforms(uniforms), next_sampler(0), values(values) { - /* empty */ + memset(this->targets, 0, sizeof(this->targets)); + } + + void start_shader() + { + this->shader_samplers_used = 0; + this->shader_shadow_samplers = 0; } private: @@ -230,8 +236,25 @@ private: * example, we may be processing the uniform in the fragment shader, but * the uniform was already processed in the vertex shader. */ - if (this->uniforms[id].storage != NULL) + if (this->uniforms[id].storage != NULL) { + /* If the uniform already has storage set from another shader stage, + * mark the samplers used for this shader stage. + */ + if (type->contains_sampler()) { + const unsigned count = MAX2(1, this->uniforms[id].array_elements); + const unsigned shadow = (type->is_array()) + ? type->fields.array->sampler_shadow : type->sampler_shadow; + + for (unsigned i = 0; i < count; i++) { + const unsigned s = this->uniforms[id].sampler + i; + + this->shader_samplers_used |= 1U << s; + this->shader_shadow_samplers |= shadow << s; + } + } + return; + } const glsl_type *base_type; if (type->is_array()) { @@ -249,6 +272,17 @@ private: * array elements for arrays. */ this->next_sampler += MAX2(1, this->uniforms[id].array_elements); + + const gl_texture_index target = base_type->sampler_index(); + const unsigned shadow = base_type->sampler_shadow; + for (unsigned i = this->uniforms[id].sampler + ; i < this->next_sampler + ; i++) { + this->targets[i] = target; + this->shader_samplers_used |= 1U << i; + this->shader_shadow_samplers |= shadow << i; + } + } else { this->uniforms[id].sampler = ~0; } @@ -270,6 +304,18 @@ private: public: union gl_constant_value *values; + + gl_texture_index targets[MAX_SAMPLERS]; + + /** + * Mask of samplers used by the current shader stage. + */ + unsigned shader_samplers_used; + + /** + * Mask of samplers used by the current shader stage for shadows. + */ + unsigned shader_shadow_samplers; }; void @@ -346,6 +392,10 @@ link_assign_uniform_locations(struct gl_shader_program *prog) if (prog->_LinkedShaders[i] == NULL) continue; + /* Reset various per-shader target counts. + */ + parcel.start_shader(); + foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); @@ -359,8 +409,14 @@ link_assign_uniform_locations(struct gl_shader_program *prog) parcel.process(var); } + + prog->_LinkedShaders[i]->active_samplers = parcel.shader_samplers_used; + prog->_LinkedShaders[i]->shadow_samplers = parcel.shader_shadow_samplers; } + assert(sizeof(prog->SamplerTargets) == sizeof(parcel.targets)); + memcpy(prog->SamplerTargets, parcel.targets, sizeof(prog->SamplerTargets)); + #ifndef NDEBUG for (unsigned i = 0; i < num_user_uniforms; i++) { assert(uniforms[i].storage != NULL); diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index e8472d446..0d85aeee6 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -246,7 +246,8 @@ count_attribute_slots(const glsl_type *t) /** * Verify that a vertex shader executable meets all semantic requirements. * - * Also sets prog->Vert.UsesClipDistance as a side effect. + * Also sets prog->Vert.UsesClipDistance and prog->Vert.ClipDistanceArraySize + * as a side effect. * * \param shader Vertex shader executable to be verified */ @@ -264,6 +265,8 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, return false; } + prog->Vert.ClipDistanceArraySize = 0; + if (prog->Version >= 130) { /* From section 7.1 (Vertex Shader Special Variables) of the * GLSL 1.30 spec: @@ -282,6 +285,10 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, return false; } prog->Vert.UsesClipDistance = clip_distance.variable_found(); + ir_variable *clip_distance_var = + shader->symbols->get_variable("gl_ClipDistance"); + if (clip_distance_var) + prog->Vert.ClipDistanceArraySize = clip_distance_var->type->length; } return true; @@ -1381,7 +1388,7 @@ public: static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y); bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog, ir_variable *output_var); - bool store(struct gl_shader_program *prog, + bool store(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_info *info, unsigned buffer, unsigned varying) const; @@ -1399,7 +1406,10 @@ public: */ bool matches_var(ir_variable *var) const { - return strcmp(var->name, this->var_name) == 0; + if (this->is_clip_distance_mesa) + return strcmp(var->name, "gl_ClipDistanceMESA") == 0; + else + return strcmp(var->name, this->var_name) == 0; } /** @@ -1408,7 +1418,10 @@ public: */ unsigned num_components() const { - return this->vector_elements * this->matrix_columns; + if (this->is_clip_distance_mesa) + return this->size; + else + return this->vector_elements * this->matrix_columns * this->size; } private: @@ -1434,11 +1447,10 @@ private: unsigned array_subscript; /** - * Which component to extract from the vertex shader output location that - * the linker assigned to this variable. -1 if all components should be - * extracted. + * True if the variable is gl_ClipDistance and the driver lowers + * gl_ClipDistance to gl_ClipDistanceMESA. */ - int single_component; + bool is_clip_distance_mesa; /** * The vertex shader output location that the linker assigned for this @@ -1484,7 +1496,7 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, this->location = -1; this->orig_name = input; - this->single_component = -1; + this->is_clip_distance_mesa = false; const char *bracket = strrchr(input, '['); @@ -1500,17 +1512,13 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, this->is_subscripted = false; } - /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, we need - * to convert a request for gl_ClipDistance[n] into a request for a - * component of gl_ClipDistanceMESA[n/4]. + /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, this + * class must behave specially to account for the fact that gl_ClipDistance + * is converted from a float[8] to a vec4[2]. */ if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance && strcmp(this->var_name, "gl_ClipDistance") == 0) { - this->var_name = "gl_ClipDistanceMESA"; - if (this->is_subscripted) { - this->single_component = this->array_subscript % 4; - this->array_subscript /= 4; - } + this->is_clip_distance_mesa = true; } return true; @@ -1530,8 +1538,6 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y) return false; if (x.is_subscripted && x.array_subscript != y.array_subscript) return false; - if (x.single_component != y.single_component) - return false; return true; } @@ -1552,27 +1558,36 @@ tfeedback_decl::assign_location(struct gl_context *ctx, /* Array variable */ const unsigned matrix_cols = output_var->type->fields.array->matrix_columns; + unsigned actual_array_size = this->is_clip_distance_mesa ? + prog->Vert.ClipDistanceArraySize : output_var->type->array_size(); if (this->is_subscripted) { /* Check array bounds. */ - if (this->array_subscript >= - (unsigned) output_var->type->array_size()) { + if (this->array_subscript >= actual_array_size) { linker_error(prog, "Transform feedback varying %s has index " - "%i, but the array size is %i.", + "%i, but the array size is %u.", this->orig_name, this->array_subscript, - output_var->type->array_size()); + actual_array_size); return false; } - this->location = - output_var->location + this->array_subscript * matrix_cols; + if (this->is_clip_distance_mesa) { + this->location = + output_var->location + this->array_subscript / 4; + } else { + this->location = + output_var->location + this->array_subscript * matrix_cols; + } this->size = 1; } else { this->location = output_var->location; - this->size = (unsigned) output_var->type->array_size(); + this->size = actual_array_size; } this->vector_elements = output_var->type->fields.array->vector_elements; this->matrix_columns = matrix_cols; - this->type = output_var->type->fields.array->gl_type; + if (this->is_clip_distance_mesa) + this->type = GL_FLOAT; + else + this->type = output_var->type->fields.array->gl_type; } else { /* Regular variable (scalar, vector, or matrix) */ if (this->is_subscripted) { @@ -1587,6 +1602,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, this->matrix_columns = output_var->type->matrix_columns; this->type = output_var->type->gl_type; } + /* From GL_EXT_transform_feedback: * A program will fail to link if: * @@ -1615,7 +1631,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, * is returned. */ bool -tfeedback_decl::store(struct gl_shader_program *prog, +tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_info *info, unsigned buffer, unsigned varying) const { @@ -1631,21 +1647,63 @@ tfeedback_decl::store(struct gl_shader_program *prog, this->orig_name); return false; } - for (unsigned index = 0; index < this->size; ++index) { + + /* From GL_EXT_transform_feedback: + * A program will fail to link if: + * + * * the total number of components to capture is greater than + * the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT + * and the buffer mode is INTERLEAVED_ATTRIBS_EXT. + */ + if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS && + info->BufferStride[buffer] + this->num_components() > + ctx->Const.MaxTransformFeedbackInterleavedComponents) { + linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " + "limit has been exceeded."); + return false; + } + + /* Verify that the checks on MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS + * and MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS are sufficient to prevent + * overflow of info->Outputs[]. In worst case we generate one entry in + * Outputs[] per component so a conservative check is to verify that the + * size of the array is greater than or equal to both + * MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS and + * MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS. + */ + assert(Elements(info->Outputs) >= + ctx->Const.MaxTransformFeedbackInterleavedComponents); + assert(Elements(info->Outputs) >= + ctx->Const.MaxTransformFeedbackSeparateComponents); + + unsigned translated_size = this->size; + if (this->is_clip_distance_mesa) + translated_size = (translated_size + 3) / 4; + unsigned components_so_far = 0; + for (unsigned index = 0; index < translated_size; ++index) { for (unsigned v = 0; v < this->matrix_columns; ++v) { - unsigned num_components = - this->single_component >= 0 ? 1 : this->vector_elements; + unsigned num_components = this->vector_elements; + info->Outputs[info->NumOutputs].ComponentOffset = 0; + if (this->is_clip_distance_mesa) { + if (this->is_subscripted) { + num_components = 1; + info->Outputs[info->NumOutputs].ComponentOffset = + this->array_subscript % 4; + } else { + num_components = MIN2(4, this->size - components_so_far); + } + } info->Outputs[info->NumOutputs].OutputRegister = this->location + v + index * this->matrix_columns; info->Outputs[info->NumOutputs].NumComponents = num_components; info->Outputs[info->NumOutputs].OutputBuffer = buffer; info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer]; - info->Outputs[info->NumOutputs].ComponentOffset = - this->single_component >= 0 ? this->single_component : 0; ++info->NumOutputs; info->BufferStride[buffer] += num_components; + components_so_far += num_components; } } + assert(components_so_far == this->num_components()); info->Varyings[varying].Name = ralloc_strdup(prog, this->orig_name); info->Varyings[varying].Type = this->type; @@ -1914,7 +1972,6 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls) { - unsigned total_tfeedback_components = 0; bool separate_attribs_mode = prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS; @@ -1933,25 +1990,9 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, for (unsigned i = 0; i < num_tfeedback_decls; ++i) { unsigned buffer = separate_attribs_mode ? i : 0; - if (!tfeedback_decls[i].store(prog, &prog->LinkedTransformFeedback, + if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback, buffer, i)) return false; - total_tfeedback_components += tfeedback_decls[i].num_components(); - } - - /* From GL_EXT_transform_feedback: - * A program will fail to link if: - * - * * the total number of components to capture is greater than - * the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT - * and the buffer mode is INTERLEAVED_ATTRIBS_EXT. - */ - if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS && - total_tfeedback_components > - ctx->Const.MaxTransformFeedbackInterleavedComponents) { - linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " - "limit has been exceeded."); - return false; } return true; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index ad289aa70..dca3613a6 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -2920,8 +2920,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, /* setup texcoords (XXX what about border?) */ setup_texture_coords(faceTarget, - 0.0f, 0.0f, /* width, height never used here */ slice, + 0, 0, /* width, height never used here */ verts[0].tex, verts[1].tex, verts[2].tex, @@ -3071,6 +3071,8 @@ get_temp_image_type(struct gl_context *ctx, GLenum baseFormat) switch (baseFormat) { case GL_RGBA: case GL_RGB: + case GL_RG: + case GL_RED: case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: @@ -3086,7 +3088,8 @@ get_temp_image_type(struct gl_context *ctx, GLenum baseFormat) case GL_DEPTH_STENCIL: return GL_UNSIGNED_INT_24_8; default: - _mesa_problem(ctx, "Unexpected format in get_temp_image_type()"); + _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()", + baseFormat); return 0; } } diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index 945f12752..b6871d0db 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -184,7 +184,7 @@ check_index_bounds(struct gl_context *ctx, GLsizei count, GLenum type, ib.ptr = indices; ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; - vbo_get_minmax_index(ctx, &prim, &ib, &min, &max); + vbo_get_minmax_indices(ctx, &prim, &ib, &min, &max, 1); if ((int)(min + basevertex) < 0 || max + basevertex > ctx->Array.ArrayObj->_MaxElement) { diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 4b3e07b85..29bfed8f5 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -303,7 +303,7 @@ _mesa_update_array_object_max_element(struct gl_context *ctx, GLuint min = ~0u; while (enabled) { - GLint attrib = _mesa_ffsll(enabled) - 1; + GLint attrib = ffsll(enabled) - 1; enabled &= ~BITFIELD64_BIT(attrib); min = update_min(min, &arrayObj->VertexAttrib[attrib]); } diff --git a/mesalib/src/mesa/main/bitset.h b/mesalib/src/mesa/main/bitset.h index c27b4c474..28b3c127e 100644 --- a/mesalib/src/mesa/main/bitset.h +++ b/mesalib/src/mesa/main/bitset.h @@ -88,7 +88,7 @@ __bitset_ffs(const BITSET_WORD *x, int n) for (i = 0; i < n; i++) { if (x[i]) - return _mesa_ffs(x[i]) + BITSET_WORDBITS * i; + return ffs(x[i]) + BITSET_WORDBITS * i; } return 0; diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index adea0f5f7..216b6ee87 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -35,6 +35,7 @@ #include "colormac.h" #include "context.h" #include "enums.h" +#include "fbobject.h" #include "mtypes.h" @@ -51,11 +52,12 @@ * \return bitmask of BUFFER_BIT_* flags */ static GLbitfield -supported_buffer_bitmask(const struct gl_context *ctx, const struct gl_framebuffer *fb) +supported_buffer_bitmask(const struct gl_context *ctx, + const struct gl_framebuffer *fb) { GLbitfield mask = 0x0; - if (fb->Name > 0) { + if (_mesa_is_user_fbo(fb)) { /* A user-created renderbuffer */ GLuint i; ASSERT(ctx->Extensions.EXT_framebuffer_object); @@ -242,7 +244,8 @@ _mesa_DrawBuffer(GLenum buffer) destMask = draw_buffer_enum_to_bitmask(buffer); if (destMask == BAD_MASK) { /* totally bogus buffer */ - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_ENUM, + "glDrawBuffer(buffer=0x%x)", buffer); return; } destMask &= supportedMask; @@ -340,6 +343,7 @@ _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); } + /** * Performs necessary state updates when _mesa_drawbuffers makes an * actual change. @@ -354,13 +358,14 @@ updated_drawbuffers(struct gl_context *ctx) struct gl_framebuffer *fb = ctx->DrawBuffer; /* Flag the FBO as requiring validation. */ - if (fb->Name != 0) { + if (_mesa_is_user_fbo(fb)) { fb->_Status = 0; } } #endif } + /** * Helper function to set the GL_DRAW_BUFFER state in the context and * current FBO. Called via glDrawBuffer(), glDrawBuffersARB() @@ -402,7 +407,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, if (n == 1) { GLuint count = 0, destMask0 = destMask[0]; while (destMask0) { - GLint bufIndex = _mesa_ffs(destMask0) - 1; + GLint bufIndex = ffs(destMask0) - 1; if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { updated_drawbuffers(ctx); fb->_ColorDrawBufferIndexes[count] = bufIndex; @@ -417,7 +422,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, GLuint count = 0; for (buf = 0; buf < n; buf++ ) { if (destMask[buf]) { - GLint bufIndex = _mesa_ffs(destMask[buf]) - 1; + GLint bufIndex = ffs(destMask[buf]) - 1; /* only one bit should be set in the destMask[buf] field */ ASSERT(_mesa_bitcount(destMask[buf]) == 1); if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { @@ -448,7 +453,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, fb->ColorDrawBuffer[buf] = GL_NONE; } - if (fb->Name == 0) { + if (_mesa_is_winsys_fbo(fb)) { /* also set context drawbuffer state */ for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { @@ -472,7 +477,7 @@ _mesa_update_draw_buffers(struct gl_context *ctx) GLuint i; /* should be a window system FBO */ - assert(ctx->DrawBuffer->Name == 0); + assert(_mesa_is_winsys_fbo(ctx->DrawBuffer)); for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) buffers[i] = ctx->Color.DrawBuffer[i]; @@ -493,7 +498,7 @@ _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) { struct gl_framebuffer *fb = ctx->ReadBuffer; - if (fb->Name == 0) { + if (_mesa_is_winsys_fbo(fb)) { /* Only update the per-context READ_BUFFER state if we're bound to * a window-system framebuffer. */ @@ -529,7 +534,7 @@ _mesa_ReadBuffer(GLenum buffer) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - if (fb->Name > 0 && buffer == GL_NONE) { + if (_mesa_is_user_fbo(fb) && buffer == GL_NONE) { /* This is legal for user-created framebuffer objects */ srcBuffer = -1; } diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c index bd5c01224..e4df120d6 100644 --- a/mesalib/src/mesa/main/clear.c +++ b/mesalib/src/mesa/main/clear.c @@ -338,7 +338,7 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) drawbuffer); return; } - else if (!ctx->RasterDiscard) { + else if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer && !ctx->RasterDiscard) { /* Save current stencil clear value, set to 'value', do the * stencil clear and restore the clear value. * XXX in the future we may have a new ctx->Driver.ClearBuffer() @@ -513,7 +513,7 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) drawbuffer); return; } - else if (!ctx->RasterDiscard) { + else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) { /* Save current depth clear value, set to 'value', do the * depth clear and restore the clear value. * XXX in the future we may have a new ctx->Driver.ClearBuffer() @@ -592,6 +592,8 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { GET_CURRENT_CONTEXT(ctx); + GLbitfield mask = 0; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); FLUSH_CURRENT(ctx, 0); @@ -622,7 +624,12 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, _mesa_update_state( ctx ); } - { + if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) + mask |= BUFFER_BIT_DEPTH; + if (ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) + mask |= BUFFER_BIT_STENCIL; + + if (mask) { /* save current clear values */ const GLclampd clearDepthSave = ctx->Depth.Clear; const GLuint clearStencilSave = ctx->Stencil.Clear; @@ -636,7 +643,7 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, ctx->Driver.ClearStencil(ctx, stencil); /* clear buffers */ - ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); + ctx->Driver.Clear(ctx, mask); /* restore */ ctx->Depth.Clear = clearDepthSave; diff --git a/mesalib/src/mesa/main/drawpix.c b/mesalib/src/mesa/main/drawpix.c index 9f5b0b36e..01983d945 100644 --- a/mesalib/src/mesa/main/drawpix.c +++ b/mesalib/src/mesa/main/drawpix.c @@ -203,6 +203,12 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, goto end; } + if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, + "glCopyPixels(multisample FBO)"); + goto end; + } + if (!_mesa_source_buffer_exists(ctx, type) || !_mesa_dest_buffer_exists(ctx, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index aefcaf350..052495907 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -79,26 +79,6 @@ static struct gl_renderbuffer DummyRenderbuffer; static struct gl_framebuffer IncompleteFramebuffer; -/** - * Is the given FBO a user-created FBO? - */ -static inline GLboolean -is_user_fbo(const struct gl_framebuffer *fb) -{ - return fb->Name != 0; -} - - -/** - * Is the given FBO a window system FBO (like an X window)? - */ -static inline GLboolean -is_winsys_fbo(const struct gl_framebuffer *fb) -{ - return fb->Name == 0; -} - - static void delete_dummy_renderbuffer(struct gl_renderbuffer *rb) { @@ -214,7 +194,7 @@ _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, { GLuint i; - assert(is_user_fbo(fb)); + assert(_mesa_is_user_fbo(fb)); switch (attachment) { case GL_COLOR_ATTACHMENT0_EXT: @@ -265,7 +245,7 @@ static struct gl_renderbuffer_attachment * _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, GLenum attachment) { - assert(is_winsys_fbo(fb)); + assert(_mesa_is_winsys_fbo(fb)); switch (attachment) { case GL_FRONT_LEFT: @@ -711,7 +691,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, GLint i; GLuint j; - assert(is_user_fbo(fb)); + assert(_mesa_is_user_fbo(fb)); numImages = 0; fb->Width = 0; @@ -1009,10 +989,10 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } - if (is_user_fbo(ctx->DrawBuffer)) { + if (_mesa_is_user_fbo(ctx->DrawBuffer)) { detach_renderbuffer(ctx, ctx->DrawBuffer, rb); } - if (is_user_fbo(ctx->ReadBuffer) + if (_mesa_is_user_fbo(ctx->ReadBuffer) && ctx->ReadBuffer != ctx->DrawBuffer) { detach_renderbuffer(ctx, ctx->ReadBuffer, rb); } @@ -1318,7 +1298,7 @@ invalidate_rb(GLuint key, void *data, void *userData) struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData; /* If this is a user-created FBO */ - if (is_user_fbo(fb)) { + if (_mesa_is_user_fbo(fb)) { GLuint i; for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = fb->Attachment + i; @@ -1395,7 +1375,8 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, if (rb->InternalFormat == internalFormat && rb->Width == (GLuint) width && - rb->Height == (GLuint) height) { + rb->Height == (GLuint) height && + rb->NumSamples == samples) { /* no change in allocation needed */ return; } @@ -1609,7 +1590,7 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) GLuint i; ASSERT(ctx->Driver.RenderTexture); - if (is_winsys_fbo(fb)) + if (_mesa_is_winsys_fbo(fb)) return; /* can't render to texture with winsys framebuffers */ for (i = 0; i < BUFFER_COUNT; i++) { @@ -1629,7 +1610,7 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) static void check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) { - if (is_winsys_fbo(fb)) + if (_mesa_is_winsys_fbo(fb)) return; /* can't render to texture with winsys framebuffers */ if (ctx->Driver.FinishRenderTexture) { @@ -1882,7 +1863,7 @@ _mesa_CheckFramebufferStatusEXT(GLenum target) return 0; } - if (is_winsys_fbo(buffer)) { + if (_mesa_is_winsys_fbo(buffer)) { /* The window system / default framebuffer is always complete */ return GL_FRAMEBUFFER_COMPLETE_EXT; } @@ -1944,7 +1925,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } /* check framebuffer binding */ - if (is_winsys_fbo(fb)) { + if (_mesa_is_winsys_fbo(fb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferTexture%sEXT", caller); return; @@ -2204,7 +2185,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, return; } - if (is_winsys_fbo(fb)) { + if (_mesa_is_winsys_fbo(fb)) { /* Can't attach new renderbuffers to a window system framebuffer */ _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); return; @@ -2285,7 +2266,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, return; } - if (is_winsys_fbo(buffer)) { + if (_mesa_is_winsys_fbo(buffer)) { /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec * says: * @@ -2332,7 +2313,8 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, switch (pname) { case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: - *params = is_winsys_fbo(buffer) ? GL_FRAMEBUFFER_DEFAULT : att->Type; + *params = _mesa_is_winsys_fbo(buffer) + ? GL_FRAMEBUFFER_DEFAULT : att->Type; return; case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: if (att->Type == GL_RENDERBUFFER_EXT) { diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h index 0a70a436d..3aee842f5 100644 --- a/mesalib/src/mesa/main/fbobject.h +++ b/mesalib/src/mesa/main/fbobject.h @@ -32,6 +32,28 @@ struct gl_context; struct gl_texture_object; + +/** + * Is the given FBO a user-created FBO? + */ +static inline GLboolean +_mesa_is_user_fbo(const struct gl_framebuffer *fb) +{ + return fb->Name != 0; +} + + +/** + * Is the given FBO a window system FBO (like an X window)? + */ +static inline GLboolean +_mesa_is_winsys_fbo(const struct gl_framebuffer *fb) +{ + return fb->Name == 0; +} + + + extern void _mesa_init_fbobjects(struct gl_context *ctx); diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 3e736fa15..afc17dc49 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -42,6 +42,7 @@ extern "C" { #include "program/programopt.h" #include "texenvprogram.h" } +#include "main/uniforms.h" #include "../glsl/glsl_types.h" #include "../glsl/ir.h" #include "../glsl/glsl_symbol_table.h" @@ -294,7 +295,7 @@ need_saturate( GLuint mode ) static GLuint translate_tex_src_bit( GLbitfield bit ) { ASSERT(bit); - return _mesa_ffs(bit) - 1; + return ffs(bit) - 1; } @@ -527,7 +528,7 @@ struct texenv_fragment_program { */ /* Texcoord override from bumpmapping. */ - struct ir_variable *texcoord_tex[MAX_TEXTURE_COORD_UNITS]; + ir_variable *texcoord_tex[MAX_TEXTURE_COORD_UNITS]; /* Reg containing texcoord for a texture unit, * needed for bump mapping, else undef. @@ -1498,25 +1499,48 @@ create_new_program(struct gl_context *ctx, struct state_key *key) /* Set the sampler uniforms, and relink to get them into the linked * program. */ - struct gl_program *fp; - fp = p.shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; + struct gl_shader *const fs = + p.shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]; + struct gl_program *const fp = fs->Program; + + _mesa_generate_parameters_list_for_uniforms(p.shader_program, fs, + fp->Parameters); + + _mesa_associate_uniform_storage(ctx, p.shader_program, fp->Parameters); for (unsigned int i = 0; i < MAX_TEXTURE_UNITS; i++) { - char *name = ralloc_asprintf(p.mem_ctx, "sampler_%d", i); + /* Enough space for 'sampler_999\0'. + */ + char name[12]; + + snprintf(name, sizeof(name), "sampler_%d", i); + int loc = _mesa_get_uniform_location(ctx, p.shader_program, name); if (loc != -1) { + unsigned base; + unsigned idx; + /* Avoid using _mesa_uniform() because it flags state * updates, so if we're generating this shader_program in a * state update, we end up recursing. Instead, just set the * value, which is picked up at re-link. */ - loc = (loc & 0xffff) + (loc >> 16); - int sampler = fp->Parameters->ParameterValues[loc][0].f; + _mesa_uniform_split_location_offset(loc, &base, &idx); + assert(idx == 0); - fp->SamplerUnits[sampler] = i; + struct gl_uniform_storage *const storage = + &p.shader_program->UniformStorage[base]; + + /* Update the storage, the SamplerUnits in the shader program, and + * the SamplerUnits in the assembly shader. + */ + storage->storage[idx].i = i; + fp->SamplerUnits[storage->sampler] = i; + p.shader_program->SamplerUnits[storage->sampler] = i; + _mesa_propagate_uniforms_to_driver_storage(storage, 0, 1); } } - _mesa_update_shader_textures_used(fp); + _mesa_update_shader_textures_used(p.shader_program, fp); (void) ctx->Driver.ProgramStringNotify(ctx, fp->Target, fp); if (!p.shader_program->LinkStatus) diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c index 19d319a56..f1ab75333 100644 --- a/mesalib/src/mesa/main/ffvertex_prog.c +++ b/mesalib/src/mesa/main/ffvertex_prog.c @@ -378,7 +378,7 @@ static struct ureg swizzle1( struct ureg reg, int x ) static struct ureg get_temp( struct tnl_program *p ) { - int bit = _mesa_ffs( ~p->temp_in_use ); + int bit = ffs( ~p->temp_in_use ); if (!bit) { _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__); exit(1); diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 730de6206..7c3c4e345 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -281,8 +281,8 @@ _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, * and return early. */ - /* For window system framebuffers, Name is zero */ - assert(fb->Name == 0); + /* Can only resize win-sys framebuffer objects */ + assert(_mesa_is_winsys_fbo(fb)); for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; @@ -408,7 +408,7 @@ update_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb) GLuint i; /* user-created framebuffers only */ - assert(fb->Name); + assert(_mesa_is_user_fbo(fb)); for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; @@ -687,7 +687,7 @@ update_color_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb) static void update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) { - if (fb->Name == 0) { + if (_mesa_is_winsys_fbo(fb)) { /* This is a window-system framebuffer */ /* Need to update the FB's GL_DRAW_BUFFER state to match the * context state (GL_READ_BUFFER too). @@ -851,7 +851,6 @@ _mesa_source_buffer_exists(struct gl_context *ctx, GLenum format) /** * As above, but for drawing operations. - * XXX could do some code merging w/ above function. */ GLboolean _mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format) diff --git a/mesalib/src/mesa/main/hash.c b/mesalib/src/mesa/main/hash.c index 4b250ad54..61c369a80 100644 --- a/mesalib/src/mesa/main/hash.c +++ b/mesalib/src/mesa/main/hash.c @@ -480,6 +480,26 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) } +/** + * Return the number of entries in the hash table. + */ +GLuint +_mesa_HashNumEntries(const struct _mesa_HashTable *table) +{ + GLuint pos, count = 0; + + for (pos = 0; pos < TABLE_SIZE; pos++) { + const struct HashEntry *entry; + for (entry = table->Table[pos]; entry; entry = entry->Next) { + count++; + } + } + + return count; +} + + + #if 0 /* debug only */ /** diff --git a/mesalib/src/mesa/main/hash.h b/mesalib/src/mesa/main/hash.h index 4f916f9d0..e935f8d39 100644 --- a/mesalib/src/mesa/main/hash.h +++ b/mesalib/src/mesa/main/hash.h @@ -63,6 +63,9 @@ extern void _mesa_HashPrint(const struct _mesa_HashTable *table); extern GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys); +extern GLuint +_mesa_HashNumEntries(const struct _mesa_HashTable *table); + extern void _mesa_test_hash_functions(void); diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c index 2469e4265..bbc6ac6e2 100644 --- a/mesalib/src/mesa/main/imports.c +++ b/mesalib/src/mesa/main/imports.c @@ -458,9 +458,8 @@ _mesa_inv_sqrtf(float n) * Find the first bit set in a word. */ int -_mesa_ffs(int32_t i) +ffs(int i) { -#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__) register int bit = 0; if (i != 0) { if ((i & 0xffff) == 0) { @@ -482,9 +481,6 @@ _mesa_ffs(int32_t i) bit++; } return bit; -#else - return ffs(i); -#endif } @@ -495,23 +491,24 @@ _mesa_ffs(int32_t i) * if no bits set. */ int -_mesa_ffsll(int64_t val) +ffsll(long long int val) { int bit; assert(sizeof(val) == 8); - bit = _mesa_ffs((int32_t)val); + bit = ffs((int) val); if (bit != 0) return bit; - bit = _mesa_ffs((int32_t)(val >> 32)); + bit = ffs((int) (val >> 32)); if (bit != 0) return 32 + bit; return 0; } -#endif +#endif /* __GNUC__ */ + #if !defined(__GNUC__) ||\ ((__GNUC__ * 100 + __GNUC_MINOR__) < 304) /* Not gcc 3.4 or later */ diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index b7e87439f..ce7b45d77 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -566,6 +566,9 @@ _mesa_inv_sqrtf(float x); extern void _mesa_init_sqrt_table(void); + +#ifndef FFS_DEFINED +#define FFS_DEFINED 1 #ifdef __GNUC__ #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(ANDROID) || defined(__APPLE__) @@ -573,10 +576,16 @@ _mesa_init_sqrt_table(void); #define ffsll __builtin_ffsll #endif -#define _mesa_ffs(i) ffs(i) -#define _mesa_ffsll(i) ffsll(i) +#else + +extern int ffs(int i); +extern int ffsll(long long int i); + +#endif /*__ GNUC__ */ +#endif /* FFS_DEFINED */ -#if ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ + +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ #define _mesa_bitcount(i) __builtin_popcount(i) #define _mesa_bitcount_64(i) __builtin_popcountll(i) #else @@ -586,16 +595,6 @@ extern unsigned int _mesa_bitcount_64(uint64_t n); #endif -#else -extern int -_mesa_ffs(int32_t i); - -extern int -_mesa_ffsll(int64_t i); - -extern unsigned int -_mesa_bitcount(unsigned int n); -#endif extern GLhalfARB _mesa_float_to_half(float f); diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index 867506c9f..03ce5361e 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -476,7 +476,7 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, GLuint *dst = (GLuint *) dstRow; for (i = j = 0, k = k0; i < (GLuint) dstWidth; i++, j += colStride, k += colStride) { - dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4); + dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; } } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 64d8c8d3f..9fdabf98c 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1894,8 +1894,6 @@ struct gl_program /** Map from sampler unit to texture unit (set by glUniform1i()) */ GLubyte SamplerUnits[MAX_SAMPLERS]; - /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */ - gl_texture_index SamplerTargets[MAX_SAMPLERS]; /** Bitmask of which register files are read/written with indirect * addressing. Mask of (1 << PROGRAM_x) bits. @@ -2185,9 +2183,17 @@ struct gl_shader unsigned Version; /**< GLSL version used for linking */ - unsigned num_samplers; /**< Number of samplers used by this shader. - * This field is only set post-linking. - */ + /** + * \name Sampler tracking + * + * \note Each of these fields is only set post-linking. + */ + /*@{*/ + unsigned num_samplers; /**< Number of samplers used by this shader. */ + GLbitfield active_samplers; /**< Bitfield of which samplers are used */ + GLbitfield shadow_samplers; /**< Samplers used for shadow sampling. */ + /*@}*/ + /** * Number of uniform components used by this shader. * @@ -2277,6 +2283,8 @@ struct gl_shader_program /** Vertex shader state - copied into gl_vertex_program at link time */ struct { GLboolean UsesClipDistance; /**< True if gl_ClipDistance is written to. */ + GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or + 0 if not present. */ } Vert; /* post-link info: */ @@ -2348,6 +2356,8 @@ struct gl_shader_state struct gl_shader_program *CurrentGeometryProgram; struct gl_shader_program *CurrentFragmentProgram; + struct gl_shader_program *_CurrentFragmentProgram; + /** * Program used by glUniform calls. * diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index 0c0e5394d..c1489d211 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -782,6 +782,11 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, return; } + if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); + return; + } + if (!_mesa_source_buffer_exists(ctx, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); return; diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index bb8f46d11..08e694673 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -132,7 +132,7 @@ _mesa_add_renderbuffer(struct gl_framebuffer *fb, fb->Attachment[bufferName].Renderbuffer == NULL); /* winsys vs. user-created buffer cross check */ - if (fb->Name) { + if (_mesa_is_user_fbo(fb)) { assert(rb->Name); } else { diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 9372d6dec..0e655a0d8 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -45,6 +45,7 @@ #include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" +#include "main/uniforms.h" #include "program/program.h" #include "program/prog_parameter.h" #include "ralloc.h" @@ -124,6 +125,8 @@ _mesa_free_shader_state(struct gl_context *ctx) NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram, NULL); + _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, + NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); } @@ -876,6 +879,33 @@ use_shader_program(struct gl_context *ctx, GLenum type, if (*target != shProg) { FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + + /* If the shader is also bound as the current rendering shader, unbind + * it from that binding point as well. This ensures that the correct + * semantics of glDeleteProgram are maintained. + */ + switch (type) { +#if FEATURE_ARB_vertex_shader + case GL_VERTEX_SHADER: + /* Empty for now. */ + break; +#endif +#if FEATURE_ARB_geometry_shader4 + case GL_GEOMETRY_SHADER_ARB: + /* Empty for now. */ + break; +#endif +#if FEATURE_ARB_fragment_shader + case GL_FRAGMENT_SHADER: + if (*target == ctx->Shader._CurrentFragmentProgram) { + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + NULL); + } + break; +#endif + } + _mesa_reference_shader_program(ctx, target, shProg); return true; } @@ -899,61 +929,6 @@ _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) } -/** - * Validate a program's samplers. - * Specifically, check that there aren't two samplers of different types - * pointing to the same texture unit. - * \return GL_TRUE if valid, GL_FALSE if invalid - */ -static GLboolean -validate_samplers(const struct gl_program *prog, char *errMsg) -{ - static const char *targetName[] = { - "TEXTURE_BUFFER", - "TEXTURE_2D_ARRAY", - "TEXTURE_1D_ARRAY", - "TEXTURE_EXTERNAL", - "TEXTURE_CUBE", - "TEXTURE_3D", - "TEXTURE_RECT", - "TEXTURE_2D", - "TEXTURE_1D", - }; - GLint targetUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - GLbitfield samplersUsed = prog->SamplersUsed; - GLuint i; - - STATIC_ASSERT(Elements(targetName) == NUM_TEXTURE_TARGETS); - - if (samplersUsed == 0x0) - return GL_TRUE; - - for (i = 0; i < Elements(targetUsed); i++) - targetUsed[i] = -1; - - /* walk over bits which are set in 'samplers' */ - while (samplersUsed) { - GLuint unit; - gl_texture_index target; - GLint sampler = _mesa_ffs(samplersUsed) - 1; - assert(sampler >= 0); - assert(sampler < Elements(prog->SamplerUnits)); - unit = prog->SamplerUnits[sampler]; - target = prog->SamplerTargets[sampler]; - if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) { - _mesa_snprintf(errMsg, 100, - "Texture unit %d is accessed both as %s and %s", - unit, targetName[targetUsed[unit]], targetName[target]); - return GL_FALSE; - } - targetUsed[unit] = target; - samplersUsed ^= (1 << sampler); - } - - return GL_TRUE; -} - - /** * Do validation of the given shader program. * \param errMsg returns error message if validation fails. @@ -963,8 +938,6 @@ static GLboolean validate_shader_program(const struct gl_shader_program *shProg, char *errMsg) { - unsigned i; - if (!shProg->LinkStatus) { return GL_FALSE; } @@ -989,12 +962,8 @@ validate_shader_program(const struct gl_shader_program *shProg, * Check: any two active samplers in the current program object are of * different types, but refer to the same texture image unit, */ - for (i = 0; i < Elements(shProg->_LinkedShaders); i++) { - if (shProg->_LinkedShaders[i] - && !validate_samplers(shProg->_LinkedShaders[i]->Program, errMsg)) { - return GL_FALSE; - } - } + if (!_mesa_sampler_uniforms_are_valid(shProg, errMsg, 100)) + return GL_FALSE; return GL_TRUE; } diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index 7e43563bd..b910543e2 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -43,6 +43,7 @@ #include "pixel.h" #include "program/program.h" #include "program/prog_parameter.h" +#include "shaderobj.h" #include "state.h" #include "stencil.h" #include "texenvprogram.h" @@ -227,7 +228,7 @@ update_program(struct gl_context *ctx) { const struct gl_shader_program *vsProg = ctx->Shader.CurrentVertexProgram; const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram; - const struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram; + struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; @@ -252,12 +253,18 @@ update_program(struct gl_context *ctx) if (fsProg && fsProg->LinkStatus && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { /* Use GLSL fragment shader */ + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + fsProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, (struct gl_fragment_program *) fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program); } else if (ctx->FragmentProgram._Enabled) { /* Use user-defined fragment program */ + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); } @@ -265,6 +272,9 @@ update_program(struct gl_context *ctx) /* Use fragment program generated from fixed-function state */ struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); + _mesa_reference_shader_program(ctx, + &ctx->Shader._CurrentFragmentProgram, + f); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, (struct gl_fragment_program *) f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program); diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 9475e84f5..39732522c 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -1900,7 +1900,7 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } /* Check that the source buffer is complete */ - if (ctx->ReadBuffer->Name) { + if (_mesa_is_user_fbo(ctx->ReadBuffer)) { if (ctx->ReadBuffer->_Status == 0) { _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); } @@ -1909,6 +1909,13 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, "glCopyTexImage%dD(invalid readbuffer)", dimensions); return GL_TRUE; } + + if (ctx->ReadBuffer->Visual.samples > 0) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, + "glCopyTexImage%dD(multisample FBO)", + dimensions); + return GL_TRUE; + } } /* Check border */ @@ -1999,7 +2006,7 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, GLenum target, GLint level) { /* Check that the source buffer is complete */ - if (ctx->ReadBuffer->Name) { + if (_mesa_is_user_fbo(ctx->ReadBuffer)) { if (ctx->ReadBuffer->_Status == 0) { _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); } @@ -2008,6 +2015,13 @@ copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, "glCopyTexImage%dD(invalid readbuffer)", dimensions); return GL_TRUE; } + + if (ctx->ReadBuffer->Visual.samples > 0) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION, + "glCopyTexSubImage%dD(multisample FBO)", + dimensions); + return GL_TRUE; + } } /* check target (proxies not allowed) */ @@ -2179,7 +2193,7 @@ check_rtt_cb(GLuint key, void *data, void *userData) const GLuint level = info->level, face = info->face; /* If this is a user-created FBO */ - if (fb->Name) { + if (_mesa_is_user_fbo(fb)) { GLuint i; /* check if any of the FBO's attachments point to 'texObj' */ for (i = 0; i < BUFFER_COUNT; i++) { diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 7ee200585..1b61d3a63 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -672,9 +672,11 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, return; } /* Don't support GL_DEPTH_COMPONENT for cube maps */ - if (t->Image[face][i]->_BaseFormat == GL_DEPTH_COMPONENT) { - incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); - return; + if (ctx->VersionMajor < 3 && !ctx->Extensions.EXT_gpu_shader4) { + if (t->Image[face][i]->_BaseFormat == GL_DEPTH_COMPONENT) { + incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); + return; + } } /* check that all six images have same size */ if (t->Image[face][i]->Width2 != width || @@ -891,7 +893,7 @@ unbind_texobj_from_fbo(struct gl_context *ctx, for (i = 0; i < n; i++) { struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer; - if (fb->Name) { + if (_mesa_is_user_fbo(fb)) { GLuint j; for (j = 0; j < BUFFER_COUNT; j++) { if (fb->Attachment[j].Type == GL_TEXTURE && diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 512965fc3..a9c64cede 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -515,9 +515,9 @@ make_temp_uint_image(struct gl_context *ctx, GLuint dims, for (k = 0; k < texComponents; k++) { GLint j = map[k]; if (j == ZERO) - newImage[i * texComponents + k] = 0.0F; + newImage[i * texComponents + k] = 0; else if (j == ONE) - newImage[i * texComponents + k] = 1.0F; + newImage[i * texComponents + k] = 1; else newImage[i * texComponents + k] = tempImage[i * logComponents + j]; } @@ -4094,7 +4094,7 @@ _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) _mesa_unpack_depth_span(ctx, srcWidth, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ dstRow, /* dst addr */ - 1.0f, srcType, src, srcPacking); + ~0U, srcType, src, srcPacking); if (srcFormat != GL_DEPTH_COMPONENT) _mesa_unpack_stencil_span(ctx, srcWidth, diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index f3d6a16ee..869f7d373 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -691,19 +691,16 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, bool flushed = false; for (i = 0; i < MESA_SHADER_TYPES; i++) { - struct gl_program *prog; - - if (shProg->_LinkedShaders[i] == NULL) - continue; - - prog = shProg->_LinkedShaders[i]->Program; + struct gl_shader *const sh = shProg->_LinkedShaders[i]; /* If the shader stage doesn't use any samplers, don't bother * checking if any samplers have changed. */ - if (prog->SamplersUsed == 0) + if (sh == NULL || sh->active_samplers == 0) continue; + struct gl_program *const prog = sh->Program; + assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits)); /* Determine if any of the samplers used by this shader stage have @@ -711,7 +708,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, */ bool changed = false; for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) { - if ((prog->SamplersUsed & (1U << j)) != 0 + if ((sh->active_samplers & (1U << j)) != 0 && (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) { changed = true; break; @@ -728,7 +725,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, shProg->SamplerUnits, sizeof(shProg->SamplerUnits)); - _mesa_update_shader_textures_used(prog); + _mesa_update_shader_textures_used(shProg, prog); (void) ctx->Driver.ProgramStringNotify(ctx, prog->Target, prog); } } @@ -933,3 +930,46 @@ _mesa_get_uniform_location(struct gl_context *ctx, return _mesa_uniform_merge_location_offset(location, offset); } + +extern "C" bool +_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg, + char *errMsg, size_t errMsgLength) +{ + const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; + + memset(unit_types, 0, sizeof(unit_types)); + + for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) { + const struct gl_uniform_storage *const storage = + &shProg->UniformStorage[i]; + const glsl_type *const t = (storage->type->is_array()) + ? storage->type->fields.array : storage->type; + + if (!t->is_sampler()) + continue; + + const unsigned count = MAX2(1, storage->type->array_size()); + for (unsigned j = 0; j < count; j++) { + const unsigned unit = storage->storage[j].i; + + /* The types of the samplers associated with a particular texture + * unit must be an exact match. Page 74 (page 89 of the PDF) of the + * OpenGL 3.3 core spec says: + * + * "It is not allowed to have variables of different sampler + * types pointing to the same texture image unit within a program + * object." + */ + if (unit_types[unit] == NULL) { + unit_types[unit] = t; + } else if (unit_types[unit] != t) { + _mesa_snprintf(errMsg, errMsgLength, + "Texture unit %d is accessed both as %s and %s", + unit, unit_types[unit]->name, t->name); + return false; + } + } + } + + return true; +} diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 685c0f13f..e0214a88a 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -60,7 +60,8 @@ * We'll use that info for state validation before rendering. */ void -_mesa_update_shader_textures_used(struct gl_program *prog) +_mesa_update_shader_textures_used(struct gl_shader_program *shProg, + struct gl_program *prog) { GLuint s; @@ -68,8 +69,8 @@ _mesa_update_shader_textures_used(struct gl_program *prog) for (s = 0; s < MAX_SAMPLERS; s++) { if (prog->SamplersUsed & (1 << s)) { - GLuint unit = prog->SamplerUnits[s]; - GLuint tgt = prog->SamplerTargets[s]; + GLuint unit = shProg->SamplerUnits[s]; + GLuint tgt = shProg->SamplerTargets[s]; assert(unit < Elements(prog->TexturesUsed)); assert(tgt < NUM_TEXTURE_TARGETS); prog->TexturesUsed[unit] |= (1 << tgt); diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index 123d7b954..7b512a527 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -212,8 +212,12 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni, unsigned count); extern void -_mesa_update_shader_textures_used(struct gl_program *prog); +_mesa_update_shader_textures_used(struct gl_shader_program *shProg, + struct gl_program *prog); +extern bool +_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg, + char *errMsg, size_t errMsgLength); extern void _mesa_init_shader_uniform_dispatch(struct _glapi_table *exec); diff --git a/mesalib/src/mesa/main/version.h b/mesalib/src/mesa/main/version.h index d288c4d55..8723c1f57 100644 --- a/mesalib/src/mesa/main/version.h +++ b/mesalib/src/mesa/main/version.h @@ -42,17 +42,6 @@ struct gl_context; #define MESA_VERSION_CODE MESA_VERSION(MESA_MAJOR, MESA_MINOR, MESA_PATCH) -/* OpenGL API version */ -#define OPENGL_MAJOR 2 -#define OPENGL_MINOR 1 -#define OPENGL_PATCH 0 -#define OPENGL_VERSION_STRING "2.1" - -/* To make version comparison easy */ -#define OPENGL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#define OPENGL_VERSION_CODE OPENGL_VERSION(OPENGL_MAJOR, OPENGL_MINOR, OPENGL_PATCH) - - extern void _mesa_compute_version(struct gl_context *ctx); diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 5a68fc51d..6a90d5ad7 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -2490,34 +2490,6 @@ print_program(struct prog_instruction *mesa_instructions, } } - -/** - * Count resources used by the given gpu program (number of texture - * samplers, etc). - */ -static void -count_resources(struct gl_program *prog) -{ - unsigned int i; - - prog->SamplersUsed = 0; - - for (i = 0; i < prog->NumInstructions; i++) { - struct prog_instruction *inst = &prog->Instructions[i]; - - if (_mesa_is_tex_instruction(inst->Opcode)) { - prog->SamplerTargets[inst->TexSrcUnit] = - (gl_texture_index)inst->TexSrcTarget; - prog->SamplersUsed |= 1 << inst->TexSrcUnit; - if (inst->TexShadow) { - prog->ShadowSamplers |= 1 << inst->TexSrcUnit; - } - } - } - - _mesa_update_shader_textures_used(prog); -} - class add_uniform_to_shader : public uniform_field_visitor { public: add_uniform_to_shader(struct gl_shader_program *shader_program, @@ -3197,7 +3169,10 @@ get_mesa_program(struct gl_context *ctx, mesa_instructions = NULL; do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER); - count_resources(prog); + + prog->SamplersUsed = shader->active_samplers; + prog->ShadowSamplers = shader->shadow_samplers; + _mesa_update_shader_textures_used(shader_program, prog); /* Set the gl_FragDepth layout. */ if (target == GL_FRAGMENT_PROGRAM_ARB) { diff --git a/mesalib/src/mesa/program/prog_print.c b/mesalib/src/mesa/program/prog_print.c index 352a80f27..46f1df0fc 100644 --- a/mesalib/src/mesa/program/prog_print.c +++ b/mesalib/src/mesa/program/prog_print.c @@ -194,7 +194,7 @@ _mesa_print_vp_inputs(GLbitfield inputs) { printf("VP Inputs 0x%x: \n", inputs); while (inputs) { - GLint attr = _mesa_ffs(inputs) - 1; + GLint attr = ffs(inputs) - 1; const char *name = arb_input_attrib_string(attr, GL_VERTEX_PROGRAM_ARB); printf(" %d: %s\n", attr, name); @@ -212,7 +212,7 @@ _mesa_print_fp_inputs(GLbitfield inputs) { printf("FP Inputs 0x%x: \n", inputs); while (inputs) { - GLint attr = _mesa_ffs(inputs) - 1; + GLint attr = ffs(inputs) - 1; const char *name = arb_input_attrib_string(attr, GL_FRAGMENT_PROGRAM_ARB); printf(" %d: %s\n", attr, name); diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c index 008e9bd10..88e6128c8 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_texture.c +++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * distribute, sub license, 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 NON-INFRINGEMENT. @@ -22,7 +22,7 @@ * 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. - * + * **************************************************************************/ /* @@ -30,7 +30,7 @@ * Keith Whitwell * Brian Paul */ - + #include "main/macros.h" #include "main/mtypes.h" @@ -182,8 +182,10 @@ st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj, return stObj->sampler_view; } + static GLboolean -update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_view, +update_single_texture(struct st_context *st, + struct pipe_sampler_view **sampler_view, GLuint texUnit) { struct pipe_context *pipe = st->pipe; @@ -233,7 +235,6 @@ update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_ st_view_format = firstImageFormat; } - /* if sampler view has changed dereference it */ if (stObj->sampler_view) { if (check_sampler_swizzle(stObj->sampler_view, @@ -251,7 +252,8 @@ update_single_texture(struct st_context *st, struct pipe_sampler_view **sampler_ return GL_TRUE; } -static void + +static void update_vertex_textures(struct st_context *st) { const struct gl_context *ctx = st->ctx; @@ -275,7 +277,8 @@ update_vertex_textures(struct st_context *st) st->state.num_vertex_textures = su + 1; } - pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], sampler_view); + pipe_sampler_view_reference(&st->state.sampler_vertex_views[su], + sampler_view); } if (ctx->Const.MaxVertexTextureImageUnits > 0) { @@ -287,7 +290,8 @@ update_vertex_textures(struct st_context *st) } } -static void + +static void update_fragment_textures(struct st_context *st) { const struct gl_context *ctx = st->ctx; @@ -319,6 +323,7 @@ update_fragment_textures(struct st_context *st) st->state.sampler_views); } + const struct st_tracked_state st_update_texture = { "st_update_texture", /* name */ { /* dirty */ @@ -328,8 +333,9 @@ const struct st_tracked_state st_update_texture = { update_fragment_textures /* update */ }; + const struct st_tracked_state st_update_vertex_texture = { - "st_update_vertex_texture", /* name */ + "st_update_vertex_texture", /* name */ { /* dirty */ _NEW_TEXTURE, /* mesa */ ST_NEW_VERTEX_PROGRAM, /* st */ @@ -337,7 +343,9 @@ const struct st_tracked_state st_update_vertex_texture = { update_vertex_textures /* update */ }; -static void + + +static void finalize_textures(struct st_context *st) { struct gl_context *ctx = st->ctx; @@ -371,7 +379,6 @@ finalize_textures(struct st_context *st) } - const struct st_tracked_state st_finalize_textures = { "st_finalize_textures", /* name */ { /* dirty */ diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index 6d6fc858d..c0554cfc7 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -990,7 +990,8 @@ st_draw_vbo(struct gl_context *ctx, /* Gallium probably doesn't want this in some cases. */ if (!index_bounds_valid) if (!all_varyings_in_vbos(arrays)) - vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, + nr_prims); for (i = 0; i < nr_prims; i++) { num_instances = MAX2(num_instances, prims[i].num_instances); diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c index fbf0349b4..a559b733a 100644 --- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c +++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c @@ -119,7 +119,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, st_validate_state(st); if (!index_bounds_valid) - vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); + vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, nr_prims); /* must get these after state validation! */ vp = st->vp; diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index a9d405436..49c874710 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -263,12 +263,6 @@ void st_init_extensions(struct st_context *st) ctx->Const.GLSLVersion = 120; _mesa_override_glsl_version(st->ctx); - /* Extensions that only depend on the GLSL version: - */ - if (ctx->Const.GLSLVersion >= 130) { - ctx->Extensions.ARB_conservative_depth = GL_TRUE; - } - /* * Extensions that are supported by all Gallium drivers: */ @@ -587,6 +581,23 @@ void st_init_extensions(struct st_context *st) #endif } + if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_INTEGERS) && + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_INTEGERS)) { + ctx->Const.NativeIntegers = GL_TRUE; + } + + if (ctx->Const.NativeIntegers) + ctx->Const.GLSLVersion = 130; + + /* Extensions that only depend on the GLSL version: + */ + if (ctx->Const.GLSLVersion >= 130) { + ctx->Extensions.ARB_conservative_depth = GL_TRUE; + ctx->Const.MaxClipPlanes = 8; + } + ctx->Extensions.NV_primitive_restart = GL_TRUE; if (!screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { st->sw_primitive_restart = GL_TRUE; @@ -703,4 +714,12 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_transform_feedback2 = GL_TRUE; } } + + if (ctx->Const.NativeIntegers && + screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_UINT, PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET) && + screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_SINT, PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET)) + ctx->Extensions.EXT_texture_integer = GL_TRUE; + } diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 3b8e2fe37..26047cfe0 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -664,6 +664,9 @@ glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op, case3(SLT, ISLT, USLT); case2iu(ISHR, USHR); + + case2fi(SSG, ISSG); + case3(ABS, IABS, IABS); default: break; } @@ -1410,10 +1413,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) } break; case ir_unop_abs: - if (result_dst.type == GLSL_TYPE_INT || result_dst.type == GLSL_TYPE_UINT) - emit(ir, TGSI_OPCODE_IABS, result_dst, op[0]); - else - emit(ir, TGSI_OPCODE_ABS, result_dst, op[0]); + emit(ir, TGSI_OPCODE_ABS, result_dst, op[0]); break; case ir_unop_sign: emit(ir, TGSI_OPCODE_SSG, result_dst, op[0]); @@ -2646,8 +2646,9 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) ir->shadow_comparitor->accept(this); /* XXX This will need to be updated for cubemap array samplers. */ - if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D && - sampler_type->sampler_array) { + if ((sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D && + sampler_type->sampler_array) || + sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) { coord_dst.writemask = WRITEMASK_W; } else { coord_dst.writemask = WRITEMASK_Z; @@ -2842,8 +2843,6 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog) if (is_tex_instruction(inst->op)) { v->samplers_used |= 1 << inst->sampler; - prog->SamplerTargets[inst->sampler] = - (gl_texture_index)inst->tex_target; if (inst->tex_shadow) { prog->ShadowSamplers |= 1 << inst->sampler; } @@ -2851,7 +2850,9 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog) } prog->SamplersUsed = v->samplers_used; - _mesa_update_shader_textures_used(prog); + + if (v->shader_program != NULL) + _mesa_update_shader_textures_used(v->shader_program, prog); } static void @@ -4181,7 +4182,7 @@ compile_tgsi_instruction(struct st_translate *t, ureg_tex_insn(ureg, inst->op, dst, num_dst, - translate_texture_target(inst->tex_target, inst->tex_shadow), + st_translate_texture_target(inst->tex_target, inst->tex_shadow), texoffsets, inst->tex_offset_num_offset, src, num_src); return; @@ -5010,13 +5011,18 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) num_clip_distances[i] = get_clip_distance_size(ir); do { + unsigned what_to_lower = MOD_TO_FRACT | DIV_TO_MUL_RCP | + EXP_TO_EXP2 | LOG_TO_LOG2; + if (options->EmitNoPow) + what_to_lower |= POW_TO_EXP2; + if (!ctx->Const.NativeIntegers) + what_to_lower |= INT_DIV_TO_MUL_RCP; + progress = false; /* Lowering */ do_mat_op_to_vec(ir); - lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2 - | LOG_TO_LOG2 | INT_DIV_TO_MUL_RCP - | ((options->EmitNoPow) ? POW_TO_EXP2 : 0))); + lower_instructions(ir, what_to_lower); progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; @@ -5087,7 +5093,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) } void -st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi, +st_translate_stream_output_info(glsl_to_tgsi_visitor *glsl_to_tgsi, const GLuint outputMapping[], struct pipe_stream_output_info *so) { diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index b83cb2339..63920a39e 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -26,16 +26,6 @@ * Chia-I Wu */ -#include "state_tracker/st_gl_api.h" - -#include "pipe/p_context.h" -#include "pipe/p_screen.h" -#include "util/u_format.h" -#include "util/u_pointer.h" -#include "util/u_inlines.h" -#include "util/u_atomic.h" -#include "util/u_surface.h" - #include "main/mtypes.h" #include "main/context.h" #include "main/mfeatures.h" @@ -54,6 +44,16 @@ #include "st_cb_flush.h" #include "st_manager.h" +#include "state_tracker/st_gl_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_pointer.h" +#include "util/u_inlines.h" +#include "util/u_atomic.h" +#include "util/u_surface.h" + /** * Cast wrapper to convert a struct gl_framebuffer to an st_framebuffer. * Return NULL if the struct gl_framebuffer is a user-created framebuffer. diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c index ac615343a..0764234bd 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -269,7 +269,7 @@ src_register( struct st_translate *t, * Map mesa texture target to TGSI texture target. */ unsigned -translate_texture_target( GLuint textarget, +st_translate_texture_target( GLuint textarget, GLboolean shadow ) { if (shadow) { @@ -279,6 +279,7 @@ translate_texture_target( GLuint textarget, case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_SHADOWRECT; case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_SHADOW1D_ARRAY; case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_SHADOW2D_ARRAY; + case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_SHADOWCUBE; default: break; } } @@ -515,7 +516,7 @@ static void emit_ddy( struct st_translate *t, -unsigned +static unsigned translate_opcode( unsigned op ) { switch( op ) { @@ -707,7 +708,7 @@ compile_instruction( ureg_tex_insn( ureg, translate_opcode( inst->Opcode ), dst, num_dst, - translate_texture_target( inst->TexSrcTarget, + st_translate_texture_target( inst->TexSrcTarget, inst->TexShadow ), NULL, 0, src, num_src ); diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.h b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.h index 0dbdf5f61..7563c8050 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.h +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.h @@ -65,10 +65,7 @@ void st_free_tokens(const struct tgsi_token *tokens); unsigned -translate_opcode(unsigned op); - -unsigned -translate_texture_target(GLuint textarget, GLboolean shadow); +st_translate_texture_target(GLuint textarget, GLboolean shadow); #if defined __cplusplus diff --git a/mesalib/src/mesa/swrast/s_aalinetemp.h b/mesalib/src/mesa/swrast/s_aalinetemp.h index 7c535669b..376ef32d0 100644 --- a/mesalib/src/mesa/swrast/s_aalinetemp.h +++ b/mesalib/src/mesa/swrast/s_aalinetemp.h @@ -1,242 +1,242 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 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. - */ - - -/* - * Antialiased line template. - */ - - -/* - * Function to render each fragment in the AA line. - * \param ix - integer fragment window X coordiante - * \param iy - integer fragment window Y coordiante - */ -static void -NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy) -{ - const SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLfloat fx = (GLfloat) ix; - const GLfloat fy = (GLfloat) iy; - const GLfloat coverage = compute_coveragef(line, ix, iy); - const GLuint i = line->span.end; - - (void) swrast; - - if (coverage == 0.0) - return; - - line->span.end++; - line->span.array->coverage[i] = coverage; - line->span.array->x[i] = ix; - line->span.array->y[i] = iy; - - /* - * Compute Z, color, texture coords, fog for the fragment by - * solving the plane equations at (ix,iy). - */ -#ifdef DO_Z - line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane); -#endif - line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane); - line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane); - line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane); - line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane); -#if defined(DO_ATTRIBS) - ATTRIB_LOOP_BEGIN - GLfloat (*attribArray)[4] = line->span.array->attribs[attr]; - if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0 - && !ctx->FragmentProgram._Current) { - /* texcoord w/ divide by Q */ - const GLuint unit = attr - FRAG_ATTRIB_TEX0; - const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]); - GLuint c; - for (c = 0; c < 3; c++) { - attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ; - } - line->span.array->lambda[unit][i] - = compute_lambda(line->attrPlane[attr][0], - line->attrPlane[attr][1], invQ, - line->texWidth[attr], line->texHeight[attr]); - } - else { - /* non-texture attrib */ - const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane); - GLuint c; - for (c = 0; c < 4; c++) { - attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW; - } - } - ATTRIB_LOOP_END -#endif - - if (line->span.end == MAX_WIDTH) { - _swrast_write_rgba_span(ctx, &(line->span)); - line->span.end = 0; /* reset counter */ - } -} - - - -/* - * Line setup - */ -static void -NAME(line)(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLfloat tStart, tEnd; /* segment start, end along line length */ - GLboolean inSegment; - GLint iLen, i; - - /* Init the LineInfo struct */ - struct LineInfo line; - line.x0 = v0->attrib[FRAG_ATTRIB_WPOS][0]; - line.y0 = v0->attrib[FRAG_ATTRIB_WPOS][1]; - line.x1 = v1->attrib[FRAG_ATTRIB_WPOS][0]; - line.y1 = v1->attrib[FRAG_ATTRIB_WPOS][1]; - line.dx = line.x1 - line.x0; - line.dy = line.y1 - line.y0; - line.len = SQRTF(line.dx * line.dx + line.dy * line.dy); - line.halfWidth = 0.5F * CLAMP(ctx->Line.Width, - ctx->Const.MinLineWidthAA, - ctx->Const.MaxLineWidthAA); - - if (line.len == 0.0 || IS_INF_OR_NAN(line.len)) - return; - - INIT_SPAN(line.span, GL_LINE); - line.span.arrayMask = SPAN_XY | SPAN_COVERAGE; - line.span.facing = swrast->PointLineFacing; - line.xAdj = line.dx / line.len * line.halfWidth; - line.yAdj = line.dy / line.len * line.halfWidth; - -#ifdef DO_Z - line.span.arrayMask |= SPAN_Z; - compute_plane(line.x0, line.y0, line.x1, line.y1, - v0->attrib[FRAG_ATTRIB_WPOS][2], v1->attrib[FRAG_ATTRIB_WPOS][2], line.zPlane); -#endif - line.span.arrayMask |= SPAN_RGBA; - if (ctx->Light.ShadeModel == GL_SMOOTH) { - compute_plane(line.x0, line.y0, line.x1, line.y1, - v0->color[RCOMP], v1->color[RCOMP], line.rPlane); - compute_plane(line.x0, line.y0, line.x1, line.y1, - v0->color[GCOMP], v1->color[GCOMP], line.gPlane); - compute_plane(line.x0, line.y0, line.x1, line.y1, - v0->color[BCOMP], v1->color[BCOMP], line.bPlane); - compute_plane(line.x0, line.y0, line.x1, line.y1, - v0->color[ACOMP], v1->color[ACOMP], line.aPlane); - } - else { - constant_plane(v1->color[RCOMP], line.rPlane); - constant_plane(v1->color[GCOMP], line.gPlane); - constant_plane(v1->color[BCOMP], line.bPlane); - constant_plane(v1->color[ACOMP], line.aPlane); - } -#if defined(DO_ATTRIBS) - { - const GLfloat invW0 = v0->attrib[FRAG_ATTRIB_WPOS][3]; - const GLfloat invW1 = v1->attrib[FRAG_ATTRIB_WPOS][3]; - line.span.arrayMask |= SPAN_LAMBDA; - compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane); - ATTRIB_LOOP_BEGIN - GLuint c; - if (swrast->_InterpMode[attr] == GL_FLAT) { - for (c = 0; c < 4; c++) { - constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]); - } - } - else { - for (c = 0; c < 4; c++) { - const GLfloat a0 = v0->attrib[attr][c] * invW0; - const GLfloat a1 = v1->attrib[attr][c] * invW1; - compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1, - line.attrPlane[attr][c]); - } - } - line.span.arrayAttribs |= (1 << attr); - if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) { - const GLuint u = attr - FRAG_ATTRIB_TEX0; - const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; - const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel]; - line.texWidth[attr] = (GLfloat) texImage->Width; - line.texHeight[attr] = (GLfloat) texImage->Height; - } - ATTRIB_LOOP_END - } -#endif - - tStart = tEnd = 0.0; - inSegment = GL_FALSE; - iLen = (GLint) line.len; - - if (ctx->Line.StippleFlag) { - for (i = 0; i < iLen; i++) { - const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; - if ((1 << bit) & ctx->Line.StipplePattern) { - /* stipple bit is on */ - const GLfloat t = (GLfloat) i / (GLfloat) line.len; - if (!inSegment) { - /* start new segment */ - inSegment = GL_TRUE; - tStart = t; - } - else { - /* still in the segment, extend it */ - tEnd = t; - } - } - else { - /* stipple bit is off */ - if (inSegment && (tEnd > tStart)) { - /* draw the segment */ - segment(ctx, &line, NAME(plot), tStart, tEnd); - inSegment = GL_FALSE; - } - else { - /* still between segments, do nothing */ - } - } - swrast->StippleCounter++; - } - - if (inSegment) { - /* draw the final segment of the line */ - segment(ctx, &line, NAME(plot), tStart, 1.0F); - } - } - else { - /* non-stippled */ - segment(ctx, &line, NAME(plot), 0.0, 1.0); - } - - _swrast_write_rgba_span(ctx, &(line.span)); -} - - - - -#undef DO_Z -#undef DO_ATTRIBS -#undef NAME +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 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. + */ + + +/* + * Antialiased line template. + */ + + +/* + * Function to render each fragment in the AA line. + * \param ix - integer fragment window X coordiante + * \param iy - integer fragment window Y coordiante + */ +static void +NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy) +{ + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLfloat fx = (GLfloat) ix; + const GLfloat fy = (GLfloat) iy; + const GLfloat coverage = compute_coveragef(line, ix, iy); + const GLuint i = line->span.end; + + (void) swrast; + + if (coverage == 0.0) + return; + + line->span.end++; + line->span.array->coverage[i] = coverage; + line->span.array->x[i] = ix; + line->span.array->y[i] = iy; + + /* + * Compute Z, color, texture coords, fog for the fragment by + * solving the plane equations at (ix,iy). + */ +#ifdef DO_Z + line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane); +#endif + line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane); + line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane); + line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane); + line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane); +#if defined(DO_ATTRIBS) + ATTRIB_LOOP_BEGIN + GLfloat (*attribArray)[4] = line->span.array->attribs[attr]; + if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0 + && !ctx->FragmentProgram._Current) { + /* texcoord w/ divide by Q */ + const GLuint unit = attr - FRAG_ATTRIB_TEX0; + const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]); + GLuint c; + for (c = 0; c < 3; c++) { + attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ; + } + line->span.array->lambda[unit][i] + = compute_lambda(line->attrPlane[attr][0], + line->attrPlane[attr][1], invQ, + line->texWidth[attr], line->texHeight[attr]); + } + else { + /* non-texture attrib */ + const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane); + GLuint c; + for (c = 0; c < 4; c++) { + attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW; + } + } + ATTRIB_LOOP_END +#endif + + if (line->span.end == MAX_WIDTH) { + _swrast_write_rgba_span(ctx, &(line->span)); + line->span.end = 0; /* reset counter */ + } +} + + + +/* + * Line setup + */ +static void +NAME(line)(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLfloat tStart, tEnd; /* segment start, end along line length */ + GLboolean inSegment; + GLint iLen, i; + + /* Init the LineInfo struct */ + struct LineInfo line; + line.x0 = v0->attrib[FRAG_ATTRIB_WPOS][0]; + line.y0 = v0->attrib[FRAG_ATTRIB_WPOS][1]; + line.x1 = v1->attrib[FRAG_ATTRIB_WPOS][0]; + line.y1 = v1->attrib[FRAG_ATTRIB_WPOS][1]; + line.dx = line.x1 - line.x0; + line.dy = line.y1 - line.y0; + line.len = SQRTF(line.dx * line.dx + line.dy * line.dy); + line.halfWidth = 0.5F * CLAMP(ctx->Line.Width, + ctx->Const.MinLineWidthAA, + ctx->Const.MaxLineWidthAA); + + if (line.len == 0.0 || IS_INF_OR_NAN(line.len)) + return; + + INIT_SPAN(line.span, GL_LINE); + line.span.arrayMask = SPAN_XY | SPAN_COVERAGE; + line.span.facing = swrast->PointLineFacing; + line.xAdj = line.dx / line.len * line.halfWidth; + line.yAdj = line.dy / line.len * line.halfWidth; + +#ifdef DO_Z + line.span.arrayMask |= SPAN_Z; + compute_plane(line.x0, line.y0, line.x1, line.y1, + v0->attrib[FRAG_ATTRIB_WPOS][2], v1->attrib[FRAG_ATTRIB_WPOS][2], line.zPlane); +#endif + line.span.arrayMask |= SPAN_RGBA; + if (ctx->Light.ShadeModel == GL_SMOOTH) { + compute_plane(line.x0, line.y0, line.x1, line.y1, + v0->color[RCOMP], v1->color[RCOMP], line.rPlane); + compute_plane(line.x0, line.y0, line.x1, line.y1, + v0->color[GCOMP], v1->color[GCOMP], line.gPlane); + compute_plane(line.x0, line.y0, line.x1, line.y1, + v0->color[BCOMP], v1->color[BCOMP], line.bPlane); + compute_plane(line.x0, line.y0, line.x1, line.y1, + v0->color[ACOMP], v1->color[ACOMP], line.aPlane); + } + else { + constant_plane(v1->color[RCOMP], line.rPlane); + constant_plane(v1->color[GCOMP], line.gPlane); + constant_plane(v1->color[BCOMP], line.bPlane); + constant_plane(v1->color[ACOMP], line.aPlane); + } +#if defined(DO_ATTRIBS) + { + const GLfloat invW0 = v0->attrib[FRAG_ATTRIB_WPOS][3]; + const GLfloat invW1 = v1->attrib[FRAG_ATTRIB_WPOS][3]; + line.span.arrayMask |= SPAN_LAMBDA; + compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane); + ATTRIB_LOOP_BEGIN + GLuint c; + if (swrast->_InterpMode[attr] == GL_FLAT) { + for (c = 0; c < 4; c++) { + constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]); + } + } + else { + for (c = 0; c < 4; c++) { + const GLfloat a0 = v0->attrib[attr][c] * invW0; + const GLfloat a1 = v1->attrib[attr][c] * invW1; + compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1, + line.attrPlane[attr][c]); + } + } + line.span.arrayAttribs |= BITFIELD64_BIT(attr); + if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) { + const GLuint u = attr - FRAG_ATTRIB_TEX0; + const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; + const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel]; + line.texWidth[attr] = (GLfloat) texImage->Width; + line.texHeight[attr] = (GLfloat) texImage->Height; + } + ATTRIB_LOOP_END + } +#endif + + tStart = tEnd = 0.0; + inSegment = GL_FALSE; + iLen = (GLint) line.len; + + if (ctx->Line.StippleFlag) { + for (i = 0; i < iLen; i++) { + const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; + if ((1 << bit) & ctx->Line.StipplePattern) { + /* stipple bit is on */ + const GLfloat t = (GLfloat) i / (GLfloat) line.len; + if (!inSegment) { + /* start new segment */ + inSegment = GL_TRUE; + tStart = t; + } + else { + /* still in the segment, extend it */ + tEnd = t; + } + } + else { + /* stipple bit is off */ + if (inSegment && (tEnd > tStart)) { + /* draw the segment */ + segment(ctx, &line, NAME(plot), tStart, tEnd); + inSegment = GL_FALSE; + } + else { + /* still between segments, do nothing */ + } + } + swrast->StippleCounter++; + } + + if (inSegment) { + /* draw the final segment of the line */ + segment(ctx, &line, NAME(plot), tStart, 1.0F); + } + } + else { + /* non-stippled */ + segment(ctx, &line, NAME(plot), 0.0, 1.0); + } + + _swrast_write_rgba_span(ctx, &(line.span)); +} + + + + +#undef DO_Z +#undef DO_ATTRIBS +#undef NAME diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c index 94b7fe34d..06824ea2c 100644 --- a/mesalib/src/mesa/swrast/s_context.c +++ b/mesalib/src/mesa/swrast/s_context.c @@ -531,7 +531,7 @@ _swrast_update_active_attribs(struct gl_context *ctx) { GLuint i, num = 0; for (i = 0; i < FRAG_ATTRIB_MAX; i++) { - if (attribsMask & (1 << i)) { + if (attribsMask & BITFIELD64_BIT(i)) { swrast->_ActiveAttribs[num++] = i; /* how should this attribute be interpolated? */ if (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1) diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index 689fe34ae..e89930353 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -175,7 +175,7 @@ interpolate_active_attribs(struct gl_context *ctx, SWspan *span, attrMask &= ~span->arrayAttribs; ATTRIB_LOOP_BEGIN - if (attrMask & (1 << attr)) { + if (attrMask & BITFIELD64_BIT(attr)) { const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; const GLfloat dv0dx = span->attrStepX[attr][0]; @@ -199,8 +199,8 @@ interpolate_active_attribs(struct gl_context *ctx, SWspan *span, v3 += dv3dx; w += dwdx; } - ASSERT((span->arrayAttribs & (1 << attr)) == 0); - span->arrayAttribs |= (1 << attr); + ASSERT((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0); + span->arrayAttribs |= BITFIELD64_BIT(attr); } ATTRIB_LOOP_END } diff --git a/mesalib/src/mesa/swrast/s_texture.c b/mesalib/src/mesa/swrast/s_texture.c index ffd78a2b8..337a52f32 100644 --- a/mesalib/src/mesa/swrast/s_texture.c +++ b/mesalib/src/mesa/swrast/s_texture.c @@ -285,7 +285,7 @@ _swrast_map_textures(struct gl_context *ctx) /* loop over enabled texture units */ while (enabledUnits) { - GLuint unit = _mesa_ffs(enabledUnits) - 1; + GLuint unit = ffs(enabledUnits) - 1; struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; _swrast_map_texture(ctx, texObj); @@ -305,7 +305,7 @@ _swrast_unmap_textures(struct gl_context *ctx) /* loop over enabled texture units */ while (enabledUnits) { - GLuint unit = _mesa_ffs(enabledUnits) - 1; + GLuint unit = ffs(enabledUnits) - 1; struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; _swrast_unmap_texture(ctx, texObj); diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index f949c34d3..17042cf8f 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -418,7 +418,7 @@ void _tnl_vbo_draw_prims(struct gl_context *ctx, struct gl_transform_feedback_object *tfb_vertcount) { if (!index_bounds_valid) - vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); + vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h index ed8fc1722..bf925ab16 100644 --- a/mesalib/src/mesa/vbo/vbo.h +++ b/mesalib/src/mesa/vbo/vbo.h @@ -127,9 +127,9 @@ int vbo_sizeof_ib_type(GLenum type); void -vbo_get_minmax_index(struct gl_context *ctx, const struct _mesa_prim *prim, - const struct _mesa_index_buffer *ib, - GLuint *min_index, GLuint *max_index); +vbo_get_minmax_indices(struct gl_context *ctx, const struct _mesa_prim *prim, + const struct _mesa_index_buffer *ib, + GLuint *min_index, GLuint *max_index, GLuint nr_prims); void vbo_use_buffer_objects(struct gl_context *ctx); diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index fec49d35e..9861b21c9 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -99,24 +99,24 @@ vbo_sizeof_ib_type(GLenum type) * If primitive restart is enabled, we need to ignore restart * indexes when computing min/max. */ -void +static void vbo_get_minmax_index(struct gl_context *ctx, const struct _mesa_prim *prim, const struct _mesa_index_buffer *ib, - GLuint *min_index, GLuint *max_index) + GLuint *min_index, GLuint *max_index, + const GLuint count) { const GLboolean restart = ctx->Array.PrimitiveRestart; const GLuint restartIndex = ctx->Array.RestartIndex; - const GLuint count = prim->count; - const void *indices; + const int index_size = vbo_sizeof_ib_type(ib->type); + const char *indices; GLuint i; + indices = (char *) ib->ptr + prim->start * index_size; if (_mesa_is_bufferobj(ib->obj)) { - indices = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr, - count * vbo_sizeof_ib_type(ib->type), - GL_MAP_READ_BIT, ib->obj); - } else { - indices = ib->ptr; + GLsizeiptr size = MIN2(count * index_size, ib->obj->Size); + indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size, + GL_MAP_READ_BIT, ib->obj); } switch (ib->type) { @@ -196,6 +196,41 @@ vbo_get_minmax_index(struct gl_context *ctx, } } +/** + * Compute min and max elements for nr_prims + */ +void +vbo_get_minmax_indices(struct gl_context *ctx, + const struct _mesa_prim *prims, + const struct _mesa_index_buffer *ib, + GLuint *min_index, + GLuint *max_index, + GLuint nr_prims) +{ + GLuint tmp_min, tmp_max; + GLuint i; + GLuint count; + + *min_index = ~0; + *max_index = 0; + + for (i = 0; i < nr_prims; i++) { + const struct _mesa_prim *start_prim; + + start_prim = &prims[i]; + count = start_prim->count; + /* Do combination if possible to reduce map/unmap count */ + while ((i + 1 < nr_prims) && + (prims[i].start + prims[i].count == prims[i+1].start)) { + count += prims[i+1].count; + i++; + } + vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count); + *min_index = MIN2(*min_index, tmp_min); + *max_index = MAX2(*max_index, tmp_max); + } +} + /** * Check that element 'j' of the array has reasonable data. diff --git a/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c index 5053852a4..4b63a13a1 100644 --- a/xorg-server/Xext/xf86bigfont.c +++ b/xorg-server/Xext/xf86bigfont.c @@ -300,7 +300,7 @@ ProcXF86BigfontQueryVersion( #endif reply.capabilities = #ifdef HAS_SHM - (client->local && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) + (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) #else 0 #endif @@ -367,7 +367,7 @@ ProcXF86BigfontQueryFont( #else switch (client->req_len) { case 2: /* client with version 1.0 libX11 */ - stuff_flags = (client->local && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); + stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); break; case 3: /* client with version 1.1 libX11 */ stuff_flags = stuff->flags; diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index b91b41f4a..44c24337a 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -3582,14 +3582,12 @@ ProcInitialConnection(ClientPtr client) REQUEST(xReq); xConnClientPrefix *prefix; int whichbyte = 1; - char order; prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); - order = prefix->byteOrder; - if (order != 'l' && order != 'B' && order != 'r' && order != 'R') + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) return client->noClientException = -1; - if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || - (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) { client->swapped = TRUE; SwapConnClientPrefix(prefix); @@ -3601,10 +3599,6 @@ ProcInitialConnection(ClientPtr client) { swaps(&stuff->length); } - if (order == 'r' || order == 'R') - { - client->local = FALSE; - } ResetCurrentRequest(client); return Success; } diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index 536026716..04d7fb59b 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -1368,7 +1368,7 @@ ScreenRestructured (ScreenPtr pScreen) for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if (!DevHasCursor(pDev)) + if (!IsFloating(pDev) && !DevHasCursor(pDev)) continue; /* GrabDevice doesn't have a confineTo field, so we don't need to @@ -3723,7 +3723,8 @@ ActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, } } - (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); + (*grabinfo->ActivateGrab)(device, grab, + ClientTimeToServerTime(event->any.time), TRUE); if (xE) { diff --git a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c index 85e38e058..0741a7294 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c @@ -586,7 +586,7 @@ ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) } rep.isCapable = isCapable; - if (!client->local || client->swapped) + if (!LocalClient(client) || client->swapped) rep.isCapable = 0; if (client->swapped) { @@ -1253,7 +1253,7 @@ ProcXF86DRIDispatch (register ClientPtr client) } } - if (!client->local) + if (!LocalClient(client)) return DRIErrorBase + XF86DRIClientNotLocal; switch (stuff->data) diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c index 4b17f152e..4bcf77efd 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c @@ -928,7 +928,7 @@ ProcXDGADispatch (ClientPtr client) { REQUEST(xReq); - if (!client->local) + if (!LocalClient(client)) return DGAErrorBase + XF86DGAClientNotLocal; #ifdef DGA_REQ_DEBUG diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c index 6e5e3f94c..6d3d5fcbc 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c @@ -1527,7 +1527,7 @@ ProcXF86VidModeGetPermissions(ClientPtr client) rep.sequenceNumber = client->sequence; rep.permissions = XF86VM_READ_PERMISSION; if (xf86GetVidModeEnabled() && - (xf86GetVidModeAllowNonLocal() || client->local)) { + (xf86GetVidModeAllowNonLocal() || LocalClient (client))) { rep.permissions |= XF86VM_WRITE_PERMISSION; } if(client->swapped) { @@ -1597,7 +1597,7 @@ ProcXF86VidModeDispatch(ClientPtr client) default: if (!xf86GetVidModeEnabled()) return VidModeErrorBase + XF86VidModeExtensionDisabled; - if (xf86GetVidModeAllowNonLocal() || client->local) { + if (xf86GetVidModeAllowNonLocal() || LocalClient (client)) { switch (stuff->data) { case X_XF86VidModeAddModeLine: return ProcXF86VidModeAddModeLine(client); @@ -2017,7 +2017,7 @@ SProcXF86VidModeDispatch(ClientPtr client) default: if (!xf86GetVidModeEnabled()) return VidModeErrorBase + XF86VidModeExtensionDisabled; - if (xf86GetVidModeAllowNonLocal() || client->local) { + if (xf86GetVidModeAllowNonLocal() || LocalClient(client)) { switch (stuff->data) { case X_XF86VidModeAddModeLine: return SProcXF86VidModeAddModeLine(client); diff --git a/xorg-server/hw/xfree86/dri/xf86dri.c b/xorg-server/hw/xfree86/dri/xf86dri.c index 723e52622..c35ba2f94 100644 --- a/xorg-server/hw/xfree86/dri/xf86dri.c +++ b/xorg-server/hw/xfree86/dri/xf86dri.c @@ -130,7 +130,7 @@ ProcXF86DRIQueryDirectRenderingCapable( } rep.isCapable = isCapable; - if (!client->local || client->swapped) + if (!LocalClient(client) || client->swapped) rep.isCapable = 0; if (client->swapped) { @@ -557,7 +557,7 @@ ProcXF86DRIDispatch ( return ProcXF86DRIQueryDirectRenderingCapable(client); } - if (!client->local) + if (!LocalClient(client)) return DRIErrorBase + XF86DRIClientNotLocal; switch (stuff->data) diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 21331559f..73ef7f25e 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -547,7 +547,7 @@ ProcDRI2Dispatch (ClientPtr client) return ProcDRI2QueryVersion(client); } - if (!client->local) + if (!LocalClient(client)) return BadRequest; switch (stuff->data) { diff --git a/xorg-server/hw/xfree86/man/xorg.conf.man b/xorg-server/hw/xfree86/man/xorg.conf.man index 57901853b..c1b3c4f2d 100644 --- a/xorg-server/hw/xfree86/man/xorg.conf.man +++ b/xorg-server/hw/xfree86/man/xorg.conf.man @@ -659,8 +659,8 @@ Allow modules built for a different, potentially incompatible version of the X server to load. Disabled by default. .TP 7 .BI "Option \*qAutoAddDevices\*q \*q" boolean \*q -If this option is disabled, then no devices will be added from HAL events. -Enabled by default. +If this option is disabled, then no devices will be added from the HAL or +udev backends. Enabled by default. .TP 7 .BI "Option \*qAutoEnableDevices\*q \*q" boolean \*q If this option is disabled, then the devices will be added (and the @@ -802,8 +802,8 @@ Recent X servers employ HAL or udev backends for input device enumeration and input hotplugging. It is usually not necessary to provide .B InputDevice -sections in the xorg.conf if hotplugging is in use. If hotplugging is -enabled, +sections in the xorg.conf if hotplugging is in use (i.e. AutoAddDevices is +enabled). If hotplugging is enabled, .B InputDevice sections using the .B mouse, kbd diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c index 7077a6c6a..55976c454 100644 --- a/xorg-server/hw/xquartz/applewm.c +++ b/xorg-server/hw/xquartz/applewm.c @@ -630,7 +630,7 @@ ProcAppleWMDispatch ( return ProcAppleWMQueryVersion(client); } - if (!client->local) + if (!LocalClient(client)) return WMErrorBase + AppleWMClientNotLocal; switch (stuff->data) @@ -693,7 +693,7 @@ SProcAppleWMDispatch ( REQUEST(xReq); /* It is bound to be non-local when there is byte swapping */ - if (!client->local) + if (!LocalClient(client)) return WMErrorBase + AppleWMClientNotLocal; /* only local clients are allowed WM access */ diff --git a/xorg-server/hw/xquartz/xpr/appledri.c b/xorg-server/hw/xquartz/xpr/appledri.c index 091145be3..44c132abc 100644 --- a/xorg-server/hw/xquartz/xpr/appledri.c +++ b/xorg-server/hw/xquartz/xpr/appledri.c @@ -133,7 +133,7 @@ ProcAppleDRIQueryDirectRenderingCapable( } rep.isCapable = isCapable; - if (!client->local) + if (!LocalClient(client)) rep.isCapable = 0; if (client->swapped) { @@ -365,7 +365,7 @@ ProcAppleDRIDispatch ( return ProcAppleDRIQueryDirectRenderingCapable(client); } - if (!client->local) + if (!LocalClient(client)) return DRIErrorBase + AppleDRIClientNotLocal; switch (stuff->data) diff --git a/xorg-server/hw/xwin/winwindowswm.c b/xorg-server/hw/xwin/winwindowswm.c index f43834d5e..577614db6 100644 --- a/xorg-server/hw/xwin/winwindowswm.c +++ b/xorg-server/hw/xwin/winwindowswm.c @@ -548,7 +548,7 @@ ProcWindowsWMDispatch (ClientPtr client) return ProcWindowsWMQueryVersion(client); } - if (!client->local) + if (!LocalClient(client)) return WMErrorBase + WindowsWMClientNotLocal; switch (stuff->data) @@ -598,7 +598,7 @@ SProcWindowsWMDispatch (ClientPtr client) REQUEST(xReq); /* It is bound to be non-local when there is byte swapping */ - if (!client->local) + if (!LocalClient(client)) return WMErrorBase + WindowsWMClientNotLocal; /* only local clients are allowed WM access */ diff --git a/xorg-server/include/dixstruct.h b/xorg-server/include/dixstruct.h index cb370519e..0a85f40b6 100644 --- a/xorg-server/include/dixstruct.h +++ b/xorg-server/include/dixstruct.h @@ -90,23 +90,23 @@ typedef struct _Client { Mask clientAsMask; pointer requestBuffer; pointer osPrivate; /* for OS layer, including scheduler */ - char swapped; - char local; - char big_requests; - char closeDownMode; - char clientGone; - char noClientException; /* this client died or needs to be - * killed */ - char clientState; + Bool swapped; ReplySwapPtr pSwapReplyFunc; XID errorValue; int sequence; + int closeDownMode; + int clientGone; + int noClientException; /* this client died or needs to be + * killed */ int ignoreCount; /* count for Attend/IgnoreClient */ - int numSaved; SaveSetElt *saveSet; - int (**requestVector) (ClientPtr /* pClient */); + int numSaved; + int (**requestVector) ( + ClientPtr /* pClient */); CARD32 req_len; /* length of current request */ + Bool big_requests; /* supports large requests */ int priority; + ClientState clientState; PrivateRec *devPrivates; unsigned short xkbClientFlags; unsigned short mapNotifyMask; @@ -114,16 +114,16 @@ typedef struct _Client { unsigned short vMajor,vMinor; KeyCode minKC,maxKC; - unsigned int replyBytesRemaining; + unsigned long replyBytesRemaining; int smart_priority; - int smart_start_tick; - int smart_stop_tick; - int smart_check_tick; + long smart_start_tick; + long smart_stop_tick; + long smart_check_tick; DeviceIntPtr clientPtr; ClientIdPtr clientIds; unsigned short majorOp, minorOp; -} ClientRec; +} ClientRec; /* * Scheduling interface diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h index 3d08511ec..3f57f4b1a 100644 --- a/xorg-server/include/misc.h +++ b/xorg-server/include/misc.h @@ -364,7 +364,8 @@ extern _X_EXPORT unsigned long serverGeneration; /* Don't use this directly, use BUG_WARN or BUG_WARN_MSG instead */ #define __BUG_WARN_MSG(cond, with_msg, ...) \ do { if (cond) { \ - ErrorF("BUG: triggered 'if (" #cond ")'\nBUG: %s:%d in %s()\n", \ + ErrorF("BUG: triggered 'if (" #cond ")'\n"); \ + ErrorF("BUG: %s:%d in %s()\n", \ __FILE__, __LINE__, __func__); \ if (with_msg) ErrorF(__VA_ARGS__); \ xorg_backtrace(); \ diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index 84dedd5cb..48ce32962 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -353,6 +353,8 @@ typedef struct sockaddr * sockaddrPtr; extern _X_EXPORT int InvalidHost(sockaddrPtr /*saddr*/, int /*len*/, ClientPtr client); +extern _X_EXPORT int LocalClient(ClientPtr /* client */); + extern _X_EXPORT int LocalClientCred(ClientPtr, int *, int *); #define LCC_UID_SET (1 << 0) diff --git a/xorg-server/include/windowstr.h b/xorg-server/include/windowstr.h index 1124dfc4c..222de31dc 100644 --- a/xorg-server/include/windowstr.h +++ b/xorg-server/include/windowstr.h @@ -87,8 +87,8 @@ typedef struct _WindowOpt { struct _OtherClients *otherClients; /* default: NULL */ struct _GrabRec *passiveGrabs; /* default: NULL */ PropertyPtr userProps; /* default: NULL */ - CARD32 backingBitPlanes; /* default: ~0L */ - CARD32 backingPixel; /* default: 0 */ + unsigned long backingBitPlanes; /* default: ~0L */ + unsigned long backingPixel; /* default: 0 */ RegionPtr boundingShape; /* default: NULL */ RegionPtr clipShape; /* default: NULL */ RegionPtr inputShape; /* default: NULL */ diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c index ed13d0a0d..b609442de 100644 --- a/xorg-server/os/access.c +++ b/xorg-server/os/access.c @@ -1045,6 +1045,13 @@ ComputeLocalClient(ClientPtr client) return FALSE; } +Bool LocalClient(ClientPtr client) +{ + if (!client->osPrivate) + return FALSE; + return ((OsCommPtr)client->osPrivate)->local_client; +} + /* * Return the uid and gid of a connected local client * @@ -1202,7 +1209,7 @@ AuthorizedClient(ClientPtr client) if (rc != Success) return rc; - return client->local ? Success : BadAccess; + return LocalClient(client) ? Success : BadAccess; } /* Add a host to the access control list. This is the external interface diff --git a/xorg-server/os/backtrace.c b/xorg-server/os/backtrace.c index 298bf1898..edaeb17c7 100644 --- a/xorg-server/os/backtrace.c +++ b/xorg-server/os/backtrace.c @@ -43,7 +43,8 @@ void xorg_backtrace(void) const char *mod; int size, i; Dl_info info; - ErrorF("\nBacktrace:\n"); + ErrorF("\n"); + ErrorF("Backtrace:\n"); size = backtrace(array, 64); for (i = 0; i < size; i++) { int rc = dladdr(array[i], &info); @@ -59,6 +60,7 @@ void xorg_backtrace(void) ErrorF("%d: %s (%p+0x%lx) [%p]\n", i, mod, info.dli_fbase, (long unsigned int)((char *) array[i] - (char *) info.dli_fbase), array[i]); } + ErrorF("\n"); } #else /* not glibc or glibc < 2.1 */ @@ -188,7 +190,8 @@ static int xorg_backtrace_pstack(void) { void xorg_backtrace(void) { - ErrorF("\nBacktrace:\n"); + ErrorF("\n"); + ErrorF("Backtrace:\n"); # ifdef HAVE_PSTACK /* First try fork/exec of pstack - otherwise fall back to walkcontext @@ -207,6 +210,7 @@ void xorg_backtrace(void) { # endif ErrorF("Failed to get backtrace info: %s\n", strerror(errno)); } + ErrorF("\n"); } # else diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index 2c90d72a9..0e557a544 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -745,7 +745,7 @@ AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) free(oc); return NullClient; } - client->local = ComputeLocalClient(client); + oc->local_client = ComputeLocalClient(client); #if !defined(WIN32) ConnectionTranslation[fd] = client->index; #else @@ -882,7 +882,7 @@ ErrorConnMax(XtransConnInfo trans_conn) xConnSetupPrefix csp; char pad[3]; struct iovec iov[3]; - char order = 0; + char byteOrder = 0; int whichbyte = 1; struct timeval waittime; fd_set mask; @@ -895,16 +895,16 @@ ErrorConnMax(XtransConnInfo trans_conn) FD_SET(fd, &mask); (void)Select(fd + 1, &mask, NULL, NULL, &waittime); /* try to read the byte-order of the connection */ - (void)_XSERVTransRead(trans_conn, &order, 1); - if (order == 'l' || order == 'B' || order == 'r' || order == 'R') + (void)_XSERVTransRead(trans_conn, &byteOrder, 1); + if ((byteOrder == 'l') || (byteOrder == 'B')) { csp.success = xFalse; csp.lengthReason = sizeof(NOROOM) - 1; csp.length = (sizeof(NOROOM) + 2) >> 2; csp.majorVersion = X_PROTOCOL; csp.minorVersion = X_PROTOCOL_REVISION; - if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || - (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) + if (((*(char *) &whichbyte) && (byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (byteOrder == 'l'))) { swaps(&csp.majorVersion); swaps(&csp.minorVersion); @@ -1032,7 +1032,7 @@ CloseDownConnection(ClientPtr client) if (FlushCallback) CallCallbacks(&FlushCallback, NULL); - if (oc->output) + if (oc->output && oc->output->count) FlushClient(client, oc, (char *)NULL, 0); #ifdef XDMCP XdmcpCloseDisplay(oc->fd); diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index 78b7260c7..f5013d774 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -84,23 +84,6 @@ SOFTWARE. CallbackListPtr ReplyCallback; CallbackListPtr FlushCallback; -typedef struct _connectionInput { - struct _connectionInput *next; - char *buffer; /* contains current client input */ - char *bufptr; /* pointer to current start of data */ - int bufcnt; /* count of bytes in buffer */ - int lenLastReq; - int size; - unsigned int ignoreBytes; /* bytes to ignore before the next request */ -} ConnectionInput, *ConnectionInputPtr; - -typedef struct _connectionOutput { - struct _connectionOutput *next; - unsigned char *buf; - int size; - int count; -} ConnectionOutput, *ConnectionOutputPtr; - static ConnectionInputPtr AllocateInputBuffer(void); static ConnectionOutputPtr AllocateOutputBuffer(void); @@ -908,7 +891,7 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) long notWritten; long todo; - if (!oco || !oco->count) + if (!oco) return 0; written = 0; padsize = padlength[extraCount & 3]; diff --git a/xorg-server/os/osdep.h b/xorg-server/os/osdep.h index c9add48ee..70e2a0726 100644 --- a/xorg-server/os/osdep.h +++ b/xorg-server/os/osdep.h @@ -108,8 +108,22 @@ typedef Bool (*AddAuthorFunc)(unsigned name_length, const char *name, unsigned data_length, char *data); #endif -typedef struct _connectionInput *ConnectionInputPtr; -typedef struct _connectionOutput *ConnectionOutputPtr; +typedef struct _connectionInput { + struct _connectionInput *next; + char *buffer; /* contains current client input */ + char *bufptr; /* pointer to current start of data */ + int bufcnt; /* count of bytes in buffer */ + int lenLastReq; + int size; + unsigned int ignoreBytes; /* bytes to ignore before the next request */ +} ConnectionInput, *ConnectionInputPtr; + +typedef struct _connectionOutput { + struct _connectionOutput *next; + int size; + unsigned char *buf; + int count; +} ConnectionOutput, *ConnectionOutputPtr; struct _osComm; @@ -148,6 +162,7 @@ typedef struct _osComm { XID auth_id; /* authorization id */ CARD32 conn_time; /* timestamp if not established, else 0 */ struct _XtransConnInfo *trans_conn; /* transport connection object */ + Bool local_client; } OsCommRec, *OsCommPtr; extern int FlushClient( diff --git a/xorg-server/render/animcur.c b/xorg-server/render/animcur.c index fddd9f81b..8d4a9c2ef 100644 --- a/xorg-server/render/animcur.c +++ b/xorg-server/render/animcur.c @@ -1,417 +1,420 @@ -/* - * - * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 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. - */ - -/* - * Animated cursors for X. Not specific to Render in any way, but - * stuck there because Render has the other cool cursor extension. - * Besides, everyone has Render. - * - * Implemented as a simple layer over the core cursor code; it - * creates composite cursors out of a set of static cursors and - * delta times between each image. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "servermd.h" -#include "scrnintstr.h" -#include "dixstruct.h" -#include "cursorstr.h" -#include "dixfontstr.h" -#include "opaque.h" -#include "picturestr.h" -#include "inputstr.h" -#include "xace.h" - -typedef struct _AnimCurElt { - CursorPtr pCursor; /* cursor to show */ - CARD32 delay; /* in ms */ -} AnimCurElt; - -typedef struct _AnimCur { - int nelt; /* number of elements in the elts array */ - AnimCurElt *elts; /* actually allocated right after the structure */ -} AnimCurRec, *AnimCurPtr; - -typedef struct _AnimScrPriv { - CloseScreenProcPtr CloseScreen; - - ScreenBlockHandlerProcPtr BlockHandler; - - CursorLimitsProcPtr CursorLimits; - DisplayCursorProcPtr DisplayCursor; - SetCursorPositionProcPtr SetCursorPosition; - RealizeCursorProcPtr RealizeCursor; - UnrealizeCursorProcPtr UnrealizeCursor; - RecolorCursorProcPtr RecolorCursor; -} AnimCurScreenRec, *AnimCurScreenPtr; - -static unsigned char empty[4]; - -static CursorBits animCursorBits = { - empty, empty, 2, 1, 1, 0, 0, 1 -}; - -static DevPrivateKeyRec AnimCurScreenPrivateKeyRec; -#define AnimCurScreenPrivateKey (&AnimCurScreenPrivateKeyRec) - -#define IsAnimCur(c) ((c) && ((c)->bits == &animCursorBits)) -#define GetAnimCur(c) ((AnimCurPtr) ((((char *)(c) + CURSOR_REC_SIZE)))) -#define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey)) -#define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p) - -#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) -#define Unwrap(as,s,elt) ((s)->elt = (as)->elt) - - -static Bool -AnimCurCloseScreen (int index, ScreenPtr pScreen) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - Bool ret; - - Unwrap(as, pScreen, CloseScreen); - - Unwrap(as, pScreen, CursorLimits); - Unwrap(as, pScreen, DisplayCursor); - Unwrap(as, pScreen, SetCursorPosition); - Unwrap(as, pScreen, RealizeCursor); - Unwrap(as, pScreen, UnrealizeCursor); - Unwrap(as, pScreen, RecolorCursor); - SetAnimCurScreen(pScreen,0); - ret = (*pScreen->CloseScreen) (index, pScreen); - free(as); - return ret; -} - -static void -AnimCurCursorLimits (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor, - BoxPtr pHotBox, - BoxPtr pTopLeftBox) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - - Unwrap (as, pScreen, CursorLimits); - if (IsAnimCur(pCursor)) - { - AnimCurPtr ac = GetAnimCur(pCursor); - - (*pScreen->CursorLimits) (pDev, pScreen, ac->elts[0].pCursor, - pHotBox, pTopLeftBox); - } - else - { - (*pScreen->CursorLimits) (pDev, pScreen, pCursor, - pHotBox, pTopLeftBox); - } - Wrap (as, pScreen, CursorLimits, AnimCurCursorLimits); -} - -/* - * This has to be a screen block handler instead of a generic - * block handler so that it is well ordered with respect to the DRI - * block handler responsible for releasing the hardware to DRI clients - */ - -static void -AnimCurScreenBlockHandler (int screenNum, - pointer blockData, - pointer pTimeout, - pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[screenNum]; - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - DeviceIntPtr dev; - Bool activeDevice = FALSE; - CARD32 now = 0, - soonest = ~0; /* earliest time to wakeup again */ - - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen) - { - if (!activeDevice) { - now = GetTimeInMillis (); - activeDevice = TRUE; - } - - if ((INT32) (now - dev->spriteInfo->anim.time) >= 0) - { - AnimCurPtr ac = GetAnimCur(dev->spriteInfo->anim.pCursor); - int elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt; - DisplayCursorProcPtr DisplayCursor; - - /* - * Not a simple Unwrap/Wrap as this - * isn't called along the DisplayCursor - * wrapper chain. - */ - DisplayCursor = pScreen->DisplayCursor; - pScreen->DisplayCursor = as->DisplayCursor; - (void) (*pScreen->DisplayCursor) (dev, - pScreen, - ac->elts[elt].pCursor); - as->DisplayCursor = pScreen->DisplayCursor; - pScreen->DisplayCursor = DisplayCursor; - - dev->spriteInfo->anim.elt = elt; - dev->spriteInfo->anim.time = now + ac->elts[elt].delay; - } - - if (soonest > dev->spriteInfo->anim.time) - soonest = dev->spriteInfo->anim.time; - } - } - - if (activeDevice) - AdjustWaitForDelay (pTimeout, soonest - now); - - Unwrap (as, pScreen, BlockHandler); - (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); - if (activeDevice) - Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler); - else - as->BlockHandler = NULL; -} - -static Bool -AnimCurDisplayCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - Bool ret; - - Unwrap (as, pScreen, DisplayCursor); - if (IsAnimCur(pCursor)) - { - if (pCursor != pDev->spriteInfo->anim.pCursor) - { - AnimCurPtr ac = GetAnimCur(pCursor); - - ret = (*pScreen->DisplayCursor) - (pDev, pScreen, ac->elts[0].pCursor); - if (ret) - { - pDev->spriteInfo->anim.elt = 0; - pDev->spriteInfo->anim.time = GetTimeInMillis () + ac->elts[0].delay; - pDev->spriteInfo->anim.pCursor = pCursor; - pDev->spriteInfo->anim.pScreen = pScreen; - - if (!as->BlockHandler) - Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler); - } - } - else - ret = TRUE; - } - else - { - pDev->spriteInfo->anim.pCursor = 0; - pDev->spriteInfo->anim.pScreen = 0; - ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); - } - Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor); - return ret; -} - -static Bool -AnimCurSetCursorPosition (DeviceIntPtr pDev, - ScreenPtr pScreen, - int x, - int y, - Bool generateEvent) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - Bool ret; - - Unwrap (as, pScreen, SetCursorPosition); - if (pDev->spriteInfo->anim.pCursor) { - pDev->spriteInfo->anim.pScreen = pScreen; - - if (!as->BlockHandler) - Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler); - } - ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); - Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); - return ret; -} - -static Bool -AnimCurRealizeCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - Bool ret; - - Unwrap (as, pScreen, RealizeCursor); - if (IsAnimCur(pCursor)) - ret = TRUE; - else - ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor); - Wrap (as, pScreen, RealizeCursor, AnimCurRealizeCursor); - return ret; -} - -static Bool -AnimCurUnrealizeCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - Bool ret; - - Unwrap (as, pScreen, UnrealizeCursor); - if (IsAnimCur(pCursor)) - { - AnimCurPtr ac = GetAnimCur(pCursor); - int i; - - if (pScreen->myNum == 0) - for (i = 0; i < ac->nelt; i++) - FreeCursor (ac->elts[i].pCursor, 0); - ret = TRUE; - } - else - ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor); - Wrap (as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); - return ret; -} - -static void -AnimCurRecolorCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor, - Bool displayed) -{ - AnimCurScreenPtr as = GetAnimCurScreen(pScreen); - - Unwrap (as, pScreen, RecolorCursor); - if (IsAnimCur(pCursor)) - { - AnimCurPtr ac = GetAnimCur(pCursor); - int i; - - for (i = 0; i < ac->nelt; i++) - (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor, - displayed && - pDev->spriteInfo->anim.elt == i); - } - else - (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed); - Wrap (as, pScreen, RecolorCursor, AnimCurRecolorCursor); -} - -Bool -AnimCurInit (ScreenPtr pScreen) -{ - AnimCurScreenPtr as; - - if (!dixRegisterPrivateKey(&AnimCurScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - as = (AnimCurScreenPtr) malloc(sizeof (AnimCurScreenRec)); - if (!as) - return FALSE; - Wrap(as, pScreen, CloseScreen, AnimCurCloseScreen); - - as->BlockHandler = NULL; - - Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits); - Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor); - Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); - Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor); - Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); - Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor); - SetAnimCurScreen(pScreen,as); - return TRUE; -} - -int -AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor, ClientPtr client, XID cid) -{ - CursorPtr pCursor; - int rc, i; - AnimCurPtr ac; - - for (i = 0; i < screenInfo.numScreens; i++) - if (!GetAnimCurScreen (screenInfo.screens[i])) - return BadImplementation; - - for (i = 0; i < ncursor; i++) - if (IsAnimCur (cursors[i])) - return BadMatch; - - pCursor = (CursorPtr) calloc(CURSOR_REC_SIZE + - sizeof (AnimCurRec) + - ncursor * sizeof (AnimCurElt), 1); - if (!pCursor) - return BadAlloc; - dixInitPrivates(pCursor, pCursor + 1, PRIVATE_CURSOR); - pCursor->bits = &animCursorBits; - pCursor->refcnt = 1; - - pCursor->foreRed = cursors[0]->foreRed; - pCursor->foreGreen = cursors[0]->foreGreen; - pCursor->foreBlue = cursors[0]->foreBlue; - - pCursor->backRed = cursors[0]->backRed; - pCursor->backGreen = cursors[0]->backGreen; - pCursor->backBlue = cursors[0]->backBlue; - - pCursor->id = cid; - - /* security creation/labeling check */ - rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR, pCursor, - RT_NONE, NULL, DixCreateAccess); - if (rc != Success) { - dixFiniPrivates(pCursor, PRIVATE_CURSOR); - free(pCursor); - return rc; - } - - /* - * Fill in the AnimCurRec - */ - animCursorBits.refcnt++; - ac = GetAnimCur (pCursor); - ac->nelt = ncursor; - ac->elts = (AnimCurElt *) (ac + 1); - - for (i = 0; i < ncursor; i++) - { - cursors[i]->refcnt++; - ac->elts[i].pCursor = cursors[i]; - ac->elts[i].delay = deltas[i]; - } - - *ppCursor = pCursor; - return Success; -} +/* + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 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. + */ + +/* + * Animated cursors for X. Not specific to Render in any way, but + * stuck there because Render has the other cool cursor extension. + * Besides, everyone has Render. + * + * Implemented as a simple layer over the core cursor code; it + * creates composite cursors out of a set of static cursors and + * delta times between each image. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "servermd.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "dixfontstr.h" +#include "opaque.h" +#include "picturestr.h" +#include "inputstr.h" +#include "xace.h" + +typedef struct _AnimCurElt { + CursorPtr pCursor; /* cursor to show */ + CARD32 delay; /* in ms */ +} AnimCurElt; + +typedef struct _AnimCur { + int nelt; /* number of elements in the elts array */ + AnimCurElt *elts; /* actually allocated right after the structure */ +} AnimCurRec, *AnimCurPtr; + +typedef struct _AnimScrPriv { + CloseScreenProcPtr CloseScreen; + + ScreenBlockHandlerProcPtr BlockHandler; + + CursorLimitsProcPtr CursorLimits; + DisplayCursorProcPtr DisplayCursor; + SetCursorPositionProcPtr SetCursorPosition; + RealizeCursorProcPtr RealizeCursor; + UnrealizeCursorProcPtr UnrealizeCursor; + RecolorCursorProcPtr RecolorCursor; +} AnimCurScreenRec, *AnimCurScreenPtr; + +static unsigned char empty[4]; + +static CursorBits animCursorBits = { + empty, empty, 2, 1, 1, 0, 0, 1 +}; + +static DevPrivateKeyRec AnimCurScreenPrivateKeyRec; +#define AnimCurScreenPrivateKey (&AnimCurScreenPrivateKeyRec) + +#define IsAnimCur(c) ((c) && ((c)->bits == &animCursorBits)) +#define GetAnimCur(c) ((AnimCurPtr) ((((char *)(c) + CURSOR_REC_SIZE)))) +#define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey)) +#define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p) + +#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func) +#define Unwrap(as,s,elt) ((s)->elt = (as)->elt) + + +static Bool +AnimCurCloseScreen (int index, ScreenPtr pScreen) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap(as, pScreen, CloseScreen); + + Unwrap(as, pScreen, CursorLimits); + Unwrap(as, pScreen, DisplayCursor); + Unwrap(as, pScreen, SetCursorPosition); + Unwrap(as, pScreen, RealizeCursor); + Unwrap(as, pScreen, UnrealizeCursor); + Unwrap(as, pScreen, RecolorCursor); + SetAnimCurScreen(pScreen,0); + ret = (*pScreen->CloseScreen) (index, pScreen); + free(as); + return ret; +} + +static void +AnimCurCursorLimits (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor, + BoxPtr pHotBox, + BoxPtr pTopLeftBox) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + + Unwrap (as, pScreen, CursorLimits); + if (IsAnimCur(pCursor)) + { + AnimCurPtr ac = GetAnimCur(pCursor); + + (*pScreen->CursorLimits) (pDev, pScreen, ac->elts[0].pCursor, + pHotBox, pTopLeftBox); + } + else + { + (*pScreen->CursorLimits) (pDev, pScreen, pCursor, + pHotBox, pTopLeftBox); + } + Wrap (as, pScreen, CursorLimits, AnimCurCursorLimits); +} + +/* + * This has to be a screen block handler instead of a generic + * block handler so that it is well ordered with respect to the DRI + * block handler responsible for releasing the hardware to DRI clients + */ + +static void +AnimCurScreenBlockHandler (int screenNum, + pointer blockData, + pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + DeviceIntPtr dev; + Bool activeDevice = FALSE; + CARD32 now = 0, + soonest = ~0; /* earliest time to wakeup again */ + + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen) + { + if (!activeDevice) { + now = GetTimeInMillis (); + activeDevice = TRUE; + } + + if ((INT32) (now - dev->spriteInfo->anim.time) >= 0) + { + AnimCurPtr ac = GetAnimCur(dev->spriteInfo->anim.pCursor); + int elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt; + DisplayCursorProcPtr DisplayCursor; + + /* + * Not a simple Unwrap/Wrap as this + * isn't called along the DisplayCursor + * wrapper chain. + */ + DisplayCursor = pScreen->DisplayCursor; + pScreen->DisplayCursor = as->DisplayCursor; + (void) (*pScreen->DisplayCursor) (dev, + pScreen, + ac->elts[elt].pCursor); + as->DisplayCursor = pScreen->DisplayCursor; + pScreen->DisplayCursor = DisplayCursor; + + dev->spriteInfo->anim.elt = elt; + dev->spriteInfo->anim.time = now + ac->elts[elt].delay; + } + + if (soonest > dev->spriteInfo->anim.time) + soonest = dev->spriteInfo->anim.time; + } + } + + if (activeDevice) + AdjustWaitForDelay (pTimeout, soonest - now); + + Unwrap (as, pScreen, BlockHandler); + (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); + if (activeDevice) + Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler); + else + as->BlockHandler = NULL; +} + +static Bool +AnimCurDisplayCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + if (IsFloating(pDev)) + return FALSE; + + Unwrap (as, pScreen, DisplayCursor); + if (IsAnimCur(pCursor)) + { + if (pCursor != pDev->spriteInfo->anim.pCursor) + { + AnimCurPtr ac = GetAnimCur(pCursor); + + ret = (*pScreen->DisplayCursor) + (pDev, pScreen, ac->elts[0].pCursor); + if (ret) + { + pDev->spriteInfo->anim.elt = 0; + pDev->spriteInfo->anim.time = GetTimeInMillis () + ac->elts[0].delay; + pDev->spriteInfo->anim.pCursor = pCursor; + pDev->spriteInfo->anim.pScreen = pScreen; + + if (!as->BlockHandler) + Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler); + } + } + else + ret = TRUE; + } + else + { + pDev->spriteInfo->anim.pCursor = 0; + pDev->spriteInfo->anim.pScreen = 0; + ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); + } + Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor); + return ret; +} + +static Bool +AnimCurSetCursorPosition (DeviceIntPtr pDev, + ScreenPtr pScreen, + int x, + int y, + Bool generateEvent) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, SetCursorPosition); + if (pDev->spriteInfo->anim.pCursor) { + pDev->spriteInfo->anim.pScreen = pScreen; + + if (!as->BlockHandler) + Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler); + } + ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); + Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); + return ret; +} + +static Bool +AnimCurRealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, RealizeCursor); + if (IsAnimCur(pCursor)) + ret = TRUE; + else + ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor); + Wrap (as, pScreen, RealizeCursor, AnimCurRealizeCursor); + return ret; +} + +static Bool +AnimCurUnrealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + Bool ret; + + Unwrap (as, pScreen, UnrealizeCursor); + if (IsAnimCur(pCursor)) + { + AnimCurPtr ac = GetAnimCur(pCursor); + int i; + + if (pScreen->myNum == 0) + for (i = 0; i < ac->nelt; i++) + FreeCursor (ac->elts[i].pCursor, 0); + ret = TRUE; + } + else + ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor); + Wrap (as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); + return ret; +} + +static void +AnimCurRecolorCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor, + Bool displayed) +{ + AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + + Unwrap (as, pScreen, RecolorCursor); + if (IsAnimCur(pCursor)) + { + AnimCurPtr ac = GetAnimCur(pCursor); + int i; + + for (i = 0; i < ac->nelt; i++) + (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor, + displayed && + pDev->spriteInfo->anim.elt == i); + } + else + (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed); + Wrap (as, pScreen, RecolorCursor, AnimCurRecolorCursor); +} + +Bool +AnimCurInit (ScreenPtr pScreen) +{ + AnimCurScreenPtr as; + + if (!dixRegisterPrivateKey(&AnimCurScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + as = (AnimCurScreenPtr) malloc(sizeof (AnimCurScreenRec)); + if (!as) + return FALSE; + Wrap(as, pScreen, CloseScreen, AnimCurCloseScreen); + + as->BlockHandler = NULL; + + Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits); + Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor); + Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); + Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor); + Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); + Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor); + SetAnimCurScreen(pScreen,as); + return TRUE; +} + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor, ClientPtr client, XID cid) +{ + CursorPtr pCursor; + int rc, i; + AnimCurPtr ac; + + for (i = 0; i < screenInfo.numScreens; i++) + if (!GetAnimCurScreen (screenInfo.screens[i])) + return BadImplementation; + + for (i = 0; i < ncursor; i++) + if (IsAnimCur (cursors[i])) + return BadMatch; + + pCursor = (CursorPtr) calloc(CURSOR_REC_SIZE + + sizeof (AnimCurRec) + + ncursor * sizeof (AnimCurElt), 1); + if (!pCursor) + return BadAlloc; + dixInitPrivates(pCursor, pCursor + 1, PRIVATE_CURSOR); + pCursor->bits = &animCursorBits; + pCursor->refcnt = 1; + + pCursor->foreRed = cursors[0]->foreRed; + pCursor->foreGreen = cursors[0]->foreGreen; + pCursor->foreBlue = cursors[0]->foreBlue; + + pCursor->backRed = cursors[0]->backRed; + pCursor->backGreen = cursors[0]->backGreen; + pCursor->backBlue = cursors[0]->backBlue; + + pCursor->id = cid; + + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR, pCursor, + RT_NONE, NULL, DixCreateAccess); + if (rc != Success) { + dixFiniPrivates(pCursor, PRIVATE_CURSOR); + free(pCursor); + return rc; + } + + /* + * Fill in the AnimCurRec + */ + animCursorBits.refcnt++; + ac = GetAnimCur (pCursor); + ac->nelt = ncursor; + ac->elts = (AnimCurElt *) (ac + 1); + + for (i = 0; i < ncursor; i++) + { + cursors[i]->refcnt++; + ac->elts[i].pCursor = cursors[i]; + ac->elts[i].delay = deltas[i]; + } + + *ppCursor = pCursor; + return Success; +} -- cgit v1.2.3