Implement a fake glXChooseVisual() and glXCreateContext() function for
use with the makecurrent tests. Likewise, implement
glMakeCurrentTestResults(), glBegin(), and glEnd().
Implement a fake glXGetClientString() for use with the getclientstr
test.
To test that vendor-implemented dispatching works in the getprocaddress
test, implement glXExampleExtensionFunction and its vendor-neutral
dispatcher in GLX_dummy, and plug each respectively into the
getProcAddress and getDispatchAddress callback functions.
This fake GL extension function is used by the glxnscreens and
makecurrent tests. This plugs the function prototype spec into
GLX_dummy's getDispatchProto() callback and adds an entry into the table
used by its getProcAddress() callback.
This fake GL extension function will be responsible for performing
various queries on the vendor library for the purposes of testing,
and also serves as a useful test of the API driver's handling of
dynamic GL entrypoints.
testx11glvndproto tests specifically the GLVendor X extension, which is
used to lookup XID -> screen and screen -> vendor mappings in the
prototype.
testglxnscreens tests that the API library successfully dispatches GL
calls to the right vendor based on this lookup.
This subtest verifies that the GLX API library's implementation of
glXGetClientString() (which takes the "union" (concatenation) of each
vendor's client string) works as expected.
This is a variant of the testglxmakecurrent subtest which links against
the libGL filter library instead of libOpenGL + libGLX. This verifies
the ELF symbol filtering works as expected.
This implements a test app, testglxmakecurrent, which verifies the
correctness of the API library's GL dispatching when a vendor's context
is current in one or more threads.
This test spawns a given number of threads each with their own separate
context and window, and has each thread make current to its given
context. The thread then calls some core GL functions and
(to-be-implemented) a GL extension function, glMakeCurrentTestResults(),
which returns the number of times each core GL function was called.
The test then compares glMakeCurrentTestResults()'s result (which should
match up with the vendor library's call count) to the application's call
count and fails if there is a mismatch.
The test is designed to only require pthreads if multiple threads are
used. This verifies that the API library's single-threaded fake pthread
wrapper functions work properly.
Add testglxmc{basic,late,loop,threads}.sh scripts, which run the
testglxmakecurrent test with different arguments for ordering of
glXGetProcAddress(), number of threads, and number of iterations.
Isolate helper functions for window creation/destruction to a separate
test_utils.c source file which will be used by later tests.
This subtest verifies that glXGetProcAddress() works for the various
classifications of "GetProcAddress-able" functions:
- GLX 1.4 functions with dispatchers implemented directly by the API
library
- GLX 1.4 extension functions with dispatchers implemented by a vendor
loaded by the API library
- Core OpenGL functions with static dispatch stubs in libGLdispatch
- Core OpenGL functions with dynamic dispatch stubs generated by
libGLdispatch
This also tests some assertions about these dispatch stubs; namely that
the core GL dispatch stubs are no-ops if no context is current.
This vendor library will be loaded by the API library in various
subtests in the test suite, and will implement the bare minimum
needed to verify features and code paths in the API library. This
includes creating a fake GL "context", making current to the
"context", and calling some GL functions.
This adds build infrastructure for unit testing the API library
using the serial test harness. TODO: this should be replaced with
the parallel test harness, as the automake documentation says the
serial harness is deprecated.
The first and last tests to be run are scripts to initialize the test
environment (an X session with a special -modulepath argument and
xorg.conf file to pick up x11glvnd) and tear it down after all unit
tests are run.
This also adds a placeholder directory for a fake vendor library
called "GLX_dummy", to be implemented later.
libOpenGL is a filter library on libGLdispatch which only exports the
core GL 1.x-4.x entrypoints.
libGL is a filter library on libGLX and libGLdispatch which only exports
the core GL 1.x-4.x entrypoints and GLX 1.4 entrypoints. This is a
backwards compatibility layer for legacy apps which link against the old
libGL.so ABI.
This is a new glapi function which takes an already-allocated
_glapi_table and fills it in using the given getProcAddress callback.
This is needed because the existing _glapi_create_table_from_handle()
function only allows clients to pass in a loader handle from which to
dlsym() entrypoints. This reduces the number of symbols required by
each vendor library and also allows vendor libraries to provide
different context-dependent entrypoints if desired when building
dispatch tables.
This replaces the _glapi_tls_{Dispatch,Context} symbols with a single
symbol, _glapi_tls_Current, which references an array of type (void*).
This allows us to easily extend mapi to accomodate additional TLS
entries, which will be necessary for storing current API state and
allowing vendors to utilize TLS entries for their own purposes.
This change is rather messy. It requires modification to both the
dispatch stub generation code and mapi's compatibility #defines in
u_current.h. This could probably be cleaned up in later changes. It's
not clear whether _glapi_{set,get}_{dispatch,context}() are even needed
anymore, but they are kept in place for backwards compatibility and to
keep this change as self-contained as possible.
FixupDispatchTable() does the work of iterating through the list of new
pending entrypoints and querying the vendor library assigned to a
dispatch table for the appropriate function address.
FindProcInList() is used to check for duplicate procs in the tracking
lists.
This is used for fixing up all current dispatch tables whenever a thread
calls GetProcAddress() on a function which has never been seen before by
GLdispatch. The fixup itself should be threadsafe since the dispatch
lock will be taken around all accesses to this list, and actual GL calls
won't be made to the newly-GetProcAddress()'ed function since the
address for this function hasn't been returned to the application yet.
Introduce two lists for tracking dynamic dispatch stubs: newProcList and
extProcList. newProcList contains stubs which were generated by a
getProcAddress call but not assigned a prototype from a vendor, and
extProcList contains stubs which have been assigned a prototype but may
still need the vendor's implementation to be plugged into the dispatch
tables.
Also introduce a generation number which is an attribute of both
dispatch stubs and dispatch tables, and a global variable,
latestGeneration. Each time __glDispatchGetProcAddress() generates a new
dispatch stub, latestGeneration is incremented and assigned to the new
dispatch stub. Dispatch tables with a generation number less than
latestGeneration need to be fixed up with functions from the extProcList
whose generation number is greater than the dispatch table's number.
After the fixup is complete, the dispatch table's generation is updated
to latestGeneration.
This also requires we track current dispatch tables globally; this will
be done in a subsequent change.
Link against glapi to get the required symbols we need.
- Replace hard-coded mapi and mesa paths in mapi makefiles with the
autoconf variables MAPI_PREFIX and MAPI_MESA_PREFIX
- In mapi_abi.py, create a new vnd-glapi printer which provides a
statically-linked glapi (implemented using mapi) with public symbols
for consumption by libGLdispatch.
- Create a vnd-glapi subfolder and makefile for building glapi in this
mode, copied from shared-glapi. The Makefile.am (not SConscript) has
been modified to build glapi_mapi_tmp.h using the vnd-glapi printer.
- Fix top-level makefile to call into the mapi/vnd-glapi subdirectory,
and configure.ac to generate the makefile at bootstrap time.
The MESA API module, mapi, and its corresponding GL submodule, glapi,
will be used by GLdispatch for implementing dynamic and static GL stub
generation and management of core GL dispatch tables.
This fills in currently unimplemented functions for packing protocol
in the client, and retrieving mappings in the server.
- XID -> screen mappings are performed by running
dixLookupResourceByType() on the appropriate resource lists. A
callback which GLX can plug into allows for the registration of
additional resources to do XID -> screen tracking (e.g. GLX
drawables).
- screen -> vendor mappings are saved in XGLVendor's screen privates
when the extension is loaded
Implement the server-side dispatching function for routing an XGLVendor
request to the right proc, but don't implement the actual lookup
functionality, yet.
This will be used to handle the corner case when a drawable XID is
passed into the API library which belongs to an X window or otherwise
has never been seen before by the process, by providing a way to lookup
which screen the corresponding drawable belongs. This still is racey
since we can't guarantee a different process won't free the XID and
cause it to be recycled as a handle for a different resource after the
lookup, but better than not being able to figure out the mapping at all.
This extension also solves the less-difficult problem of mapping a
screen to a vendor name (though it may make more sense to at some point
directly map drawables to a vendor to better support render-offload
scenarios).
Move the GLdispatch header file to its own directory in src/GLdispatch,
and build a real DSO that GLX will depend on. In GLdispatch.c, add stub
functions which will later be fleshed out.
This implements thin wrappers around libGLdispatch which allow vendors
to manage their own dispatch tables. See documentation in the interface
header file libglxabi.h for more details.
Add a new header file, GLdispatch.h, which defines an API for
window-system libraries such as libGLX to manage core GL dispatch tables
as well as TLS. Refactor the __GLXAPIState to be derived from
__GLdispatchAPIState, make __GLXvendorInfo::glDispatch type
__GLdispatchTable, and implement make current/get current functionality
using this API.
At some point this API will be implemented in a shared library used by
both libGLX and libEGL.
Set the __glXDispatchNoopPtr statically to the __glXDispatchNoop
dispatch table, defined in libglxnoop.c.
Define no-op GLX 1.4 templates in libglxnoopdefs.h, which is included by
libglxnoop.c. We do this instead of defining the no-op functions
directly because these functions will also be needed by the libGL filter
library. To facilitate code sharing, these templates use GLXNOOP and
NOOP_FUNC() macros to respectively define the function qualifiers and
prefix (e.g. "glX") of each no-op function.
This function is an implementation of the fetchDispatchEntry export,
which is called by vendor-implemented GLX dipsatchers to fetch a
dispatch table entry given a logical dispatch table index.
This change also implements the logic for assigning dispatch table
indices to GLX entrypoints at glXGetProcAddress() time. The dynamic
dispatch table is actually a hashtable which uses the "index" as a key,
and not a flat array, to prevent wasted memory usage from sparse
dispatch tables. Since GLX entrypoints are generally not
performance-critical this should be fine.
This implements __glXLookupVendorByName(), which is responsible for
checking a hash table for existing loaded vendors with the given name,
and loading the vendor with that name if no existing vendors are found.
This also implements __glXGetGLXDispatchAddress(), which iterates
through this hash table checking whether each loaded vendor supports
dispatching to the given GLX entrypoint.
This function, which looks up a vendor given a screen number, is used
by several helper functions which look up core GL and GLX dispatch
tables given a screen number, and directly by the API library's make
curent proc. This relies on the (still unimplemented) function
__glXLookupVendorByName().
This also doubles as a way to store addresses of locally-exported GLX
functions; we use a pthread_once() callback to initialize the table
with these addresses.
libglxmapping.c implements functions needed for libGLX to map function
calls to vendors for dispatching.
libglxnoop.h contains a pointer to a no-op dispatch table.
These will be re-implemented in a later change.
This is a wrapper library around libpthread which implements
single-threaded fallbacks in case the API library is loaded in an
application which does not link against pthreads.
This makes use of a (still unimplemented) helper function called
MakeContextCurrentInternal() to actually perform the required API
library work for make current.
- libglxabipriv.h: This is a simple wrapper around libglxabi.h which
defines the static dispatch table to be the same as the set of
functions exported by the vendor (they could potentially differ).
- libglxcurrent.h: This defines a current "API state" struct which
encapsulates the API library's knowledge of the current display,
read/draw drawables, dispatch tables, and vendor (owning the current
context). The glXGetCurrent*() functions are implemented by
retrieving various fields from this API state.
- libglxmapping.h: This defines a "vendor info" struct which contains
information about a loaded vendor. It also provides accessor functions
for retrieving the dispatch table given a screen, and functions for
adding/removing mappings from various keys (Context, FBConfig,
Drawable) to screens.
- libglx.c: Replace the dummy GetStaticDispatch() function with calls to
the API in libglxmapping.h to retrieve the right dispatch table.