OpenGL client attribute stack

The Neverwinter Nights demo's ordinary New → Select Premade Character → Aluvian Darkstar → Prelude loading route stopped at glPushClientAttrib(2) at batch 192852 (call 0x71afb4, return 0x71afba). The generic native encoder now implements client push/pop rather than bypassing that call.

The stack is per context, initially empty, with sixteen frames. The array group saves all implemented vertex, normal, color and both texture-coordinate descriptors, enable bits, pointer validity and the active client texture unit. It restores pointers, not copies of guest array contents. Current color, normal and texture coordinates belong to server state and are not restored. The pixel group saves the existing unpack alignment, row length, skipped rows, skipped pixels and LSB-first modes. Native bitmap state, software texture alignment and ordered host texture alignment are restored together.

Zero masks occupy a frame without restoring state. Each defined bit selects its group, so GL_CLIENT_ALL_ATTRIB_BITS selects both; otherwise unused bits select nothing. This follows the bitfield groups in the Khronos glPushClientAttrib reference, whose error list contains stack overflow/underflow rather than invalid-mask errors. Its multitexture note requires all units and the client selector. Overflow, underflow and calls within Begin/End leave the stack unchanged. Allocation failure reports out-of-memory. Depth/limit and supported unpack queries report the native values. Client pushes/pops execute immediately during display-list compilation and are not recorded. Context deletion/reset reclaims outstanding frames. Server attribute pop no longer restores the host client unpack alignment.

This covers the client state already implemented by this renderer. It does not implement index/edge-flag arrays, buffer objects, additional pack/unpack parameters, or fix existing image/readback limitations. In particular, bitmap unpack row/skip/LSB support is broader than texture-upload layout support. The stack change does not claim those missing operations are implemented.

Validation: canonical full build; test-opengl-client-attrib.js, bitmap, display-list, unpack-alignment, fixed-function, native-encoder and Worker regressions. The client test compares real native packed vertex payloads after descriptor restoration, checks pixel upload bytes/alignment, selective and nested masks, errors, queries, context deletion, pointer validity, server/client separation and immediate display-list behavior. Logs reside remotely in gl-client-work/scratch/client-attrib/. This API regression alone establishes neither completed NWN loading nor world rendering/gameplay.

Negative control: removing only the vertex-pointer restoration fails the actual packed-vertex comparison; source was restored afterward. Candidate Wasm SHA-256: 79a828167326142433105270a3cd53fe33a3ce934f71116451e8948315b44c93.