Usage ===== texprof.[ch] implements a simple texture profiling mechanism. If LIBGL_PROFILE_SERVER is set to [HOST]:PORT (HOST is optional), then the library starts up a separate profiling thread that connects to the profiling server, then listens for requests from the server. At any point, the server can request the changes to the texture state since the last update. This meant for use with a profiler such as 'texturetop'. texturetop is a simple program that justs displays the current textures to a terminal in a format to the classic 'top' program. texturetop displays the port it is listening on when started; or it can be run on a specific port. Note that there is no security in the protocol, so using it over a public network is not really advisable. texturetop currently listens only on the loopback interface. Protocol ======== The protocol is a simple line-based text protocol. Lines are separated by carriage-return/linefeed pairs (\r\n). The maximum length of any line, including the trailing \r\n is 1024 bytes. Where a space occurs in the command description below, multiple spaces may be substituted. Trailing spaces (but not leading spaces) are permitted for lines. Lines consisting only of spaces are ignored. Types in the protocol: STRING Non-empty string of ASCII characters, excluding control characters. (\t,\r,\n are among the excluded characters space is permitted in every position but the first and last) ID A 64-bit integer encoded in hex. Either upper or lower case digits (a-f or A-F) are permitted. A leading 0x is not required or permittted. The HELLO command: After a client connects to the profiling port, it sends the HELLO command: HELLO is used only for debug purposes and is uninterpreted. The server responds and echos: HELLO may be displayed to the user. should be the minimum of and the server's maximum supported protocol version. Following the echo of HELLO, the server sends any number of objects, indicating the current state of the server. The list of objects is terminated by a single line: END HELLO The UPDATE command: The update command requests a UPDATE from the server: UPDATE The echos the UPDATE command UPDATE followed by the any objects that have changed since the initial HELLO or the last UPDATE. Only attributes that have changed are echoed. The response can also contain lines DELETE To delete a previously created objects. Objects: Two objects types are currently supported, HEAP and TEXTURE HEAP NAME= SIZE= END HEAP NAME: user visible name of the texture heap SIZE: size of the texture heap in bytes TEXTURE WIDTH= HEIGHT= MAIN_SIZE= HEAP={,} HEAP_TS= HEAP_SIZE= MODIFIED_TS= END TEXTURE WIDTH: Width of the texture, in texels HEIGHT: Width of the texture, in texels MAIN_SIZE: Amount of main memory occopied by the texture, in bytes HEAP: current heap for the texture HEAP_TS: timestamp of when the texture was moved to that heap HEAP_SIZE: amount of heap occupied by the texture, in bytes Zero or more space characters can occur before or after the '=' sign. The GOODBYE command: The GOODBYE command indicates the end of the session. The server responds by closing the connection. The command is not echoed. GOODBYE A closed TCP connection should be treated the same as a GOODBYE command. In response to any comand, the server can also respond with a single-line error message. Defined error messages are: ERROR MEMORY Server couldn't allocate memory ERROR After sending an error message, the connection will immediately be closed. No mechanism for recovery is included. Implementation notes ==================== The primary goal of the implementation of textprof within the DRI is to influence the behavior of the rendering thread(s) as little as possible. Secondary goals: Be minimally intrusive in the rest of the code. Avoid blocking the rendering thread; blocking the rendering thread could lead to deadlocks. Make memory failure allocation failure harmless to prevent needing error handling in the ain code. Because we need to handle network input/outut, and because we want to avoid blocking the main thread, a separate thread is used. To decouple the main thread and the profiling thread, we restrict the locked portions of the state as much as possible. A copy is maintained of texture state, and lists of textures and heaps so that the profiling thread can do network IO without locking. Heaps can't currently be destroyed, though that is supported by the protocol. The main difficulty of the profiling thread is that it needs to handle both updates to the shared state and also network input/output, but Unix has no good way of integrating waiting on thread primitives and on IO (other than using separate threads for IO). We handle this in a classic fashion by using a pipe to wake up the thead when something is added to the request queue: The profile thread looks: profile.poll_waiting = True profile.unlock() poll(profile.fds) profile.lock() if (!profile.poll_waiting) read_a_byte(profile.wakeup_pipe_out) To wake up the main thread after adding a request to the queue looks like: profile.lock() if (profile.poll_waiting) profile.poll_waiting = False write_a_byte(profile.wakeup_pipe_out) profile.unlock() === Owen Taylor 5 November 2004