Path: blob/21.2-virgl/src/glx/indirect_vertex_array.c
4558 views
/*1* (C) Copyright IBM Corporation 2004, 20052* All Rights Reserved.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sub license,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL18* IBM,19* AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,20* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF21* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE22* SOFTWARE.23*/2425#include <inttypes.h>26#include <assert.h>27#include <string.h>2829#include "util/compiler.h"3031#include "glxclient.h"32#include "indirect.h"33#include <GL/glxproto.h>34#include "glxextensions.h"35#include "indirect_vertex_array.h"36#include "indirect_vertex_array_priv.h"3738#define __GLX_PAD(n) (((n)+3) & ~3)3940/**41* \file indirect_vertex_array.c42* Implement GLX protocol for vertex arrays and vertex buffer objects.43*44* The most important function in this fill is \c fill_array_info_cache.45* The \c array_state_vector contains a cache of the ARRAY_INFO data sent46* in the DrawArrays protocol. Certain operations, such as enabling or47* disabling an array, can invalidate this cache. \c fill_array_info_cache48* fills-in this data. Additionally, it examines the enabled state and49* other factors to determine what "version" of DrawArrays protocoal can be50* used.51*52* Current, only two versions of DrawArrays protocol are implemented. The53* first version is the "none" protocol. This is the fallback when the54* server does not support GL 1.1 / EXT_vertex_arrays. It is implemented55* by sending batches of immediate mode commands that are equivalent to the56* DrawArrays protocol.57*58* The other protocol that is currently implemented is the "old" protocol.59* This is the GL 1.1 DrawArrays protocol. The only difference between GL60* 1.1 and EXT_vertex_arrays is the opcode used for the DrawArrays command.61* This protocol is called "old" because the ARB is in the process of62* defining a new protocol, which will probably be called wither "new" or63* "vbo", to support multiple texture coordinate arrays, generic attributes,64* and vertex buffer objects.65*66* \author Ian Romanick <[email protected]>67*/6869static void emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count);70static void emit_DrawArrays_old(GLenum mode, GLint first, GLsizei count);7172static void emit_DrawElements_none(GLenum mode, GLsizei count, GLenum type,73const GLvoid * indices);74static void emit_DrawElements_old(GLenum mode, GLsizei count, GLenum type,75const GLvoid * indices);767778static GLubyte *emit_element_none(GLubyte * dst,79const struct array_state_vector *arrays,80unsigned index);81static GLubyte *emit_element_old(GLubyte * dst,82const struct array_state_vector *arrays,83unsigned index);84static struct array_state *get_array_entry(const struct array_state_vector85*arrays, GLenum key,86unsigned index);87static void fill_array_info_cache(struct array_state_vector *arrays);88static GLboolean validate_mode(struct glx_context * gc, GLenum mode);89static GLboolean validate_count(struct glx_context * gc, GLsizei count);90static GLboolean validate_type(struct glx_context * gc, GLenum type);919293/**94* Table of sizes, in bytes, of a GL types. All of the type enums are be in95* the range 0x1400 - 0x140F. That includes types added by extensions (i.e.,96* \c GL_HALF_FLOAT_NV). This elements of this table correspond to the97* type enums masked with 0x0f.98*99* \notes100* \c GL_HALF_FLOAT_NV is not included. Neither are \c GL_2_BYTES,101* \c GL_3_BYTES, or \c GL_4_BYTES.102*/103const GLuint __glXTypeSize_table[16] = {1041, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0105};106107108/**109* Free the per-context array state that was allocated with110* __glXInitVertexArrayState().111*/112void113__glXFreeVertexArrayState(struct glx_context * gc)114{115__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);116struct array_state_vector *arrays = state->array_state;117118if (arrays) {119free(arrays->stack);120arrays->stack = NULL;121free(arrays->arrays);122arrays->arrays = NULL;123free(arrays);124state->array_state = NULL;125}126}127128129/**130* Initialize vertex array state of a GLX context.131*132* \param gc GLX context whose vertex array state is to be initialized.133*134* \warning135* This function may only be called after struct glx_context::gl_extension_bits,136* struct glx_context::server_minor, and __GLXcontext::server_major have been137* initialized. These values are used to determine what vertex arrays are138* supported.139*/140void141__glXInitVertexArrayState(struct glx_context * gc)142{143__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);144struct array_state_vector *arrays;145146unsigned array_count;147int texture_units = 1, vertex_program_attribs = 0;148unsigned i, j;149150GLboolean got_fog = GL_FALSE;151GLboolean got_secondary_color = GL_FALSE;152153154arrays = calloc(1, sizeof(struct array_state_vector));155state->array_state = arrays;156157if (arrays == NULL) {158__glXSetError(gc, GL_OUT_OF_MEMORY);159return;160}161162arrays->old_DrawArrays_possible = !state->NoDrawArraysProtocol;163arrays->new_DrawArrays_possible = GL_FALSE;164arrays->DrawArrays = NULL;165166arrays->active_texture_unit = 0;167168169/* Determine how many arrays are actually needed. Only arrays that170* are supported by the server are create. For example, if the server171* supports only 2 texture units, then only 2 texture coordinate arrays172* are created.173*174* At the very least, GL_VERTEX_ARRAY, GL_NORMAL_ARRAY,175* GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY, and176* GL_EDGE_FLAG_ARRAY are supported.177*/178179array_count = 5;180181if (__glExtensionBitIsEnabled(gc, GL_EXT_fog_coord_bit)182|| (gc->server_major > 1) || (gc->server_minor >= 4)) {183got_fog = GL_TRUE;184array_count++;185}186187if (__glExtensionBitIsEnabled(gc, GL_EXT_secondary_color_bit)188|| (gc->server_major > 1) || (gc->server_minor >= 4)) {189got_secondary_color = GL_TRUE;190array_count++;191}192193if (__glExtensionBitIsEnabled(gc, GL_ARB_multitexture_bit)194|| (gc->server_major > 1) || (gc->server_minor >= 3)) {195__indirect_glGetIntegerv(GL_MAX_TEXTURE_UNITS, &texture_units);196}197198if (__glExtensionBitIsEnabled(gc, GL_ARB_vertex_program_bit)) {199__indirect_glGetProgramivARB(GL_VERTEX_PROGRAM_ARB,200GL_MAX_PROGRAM_ATTRIBS_ARB,201&vertex_program_attribs);202}203204arrays->num_texture_units = texture_units;205arrays->num_vertex_program_attribs = vertex_program_attribs;206array_count += texture_units + vertex_program_attribs;207arrays->num_arrays = array_count;208arrays->arrays = calloc(array_count, sizeof(struct array_state));209210if (arrays->arrays == NULL) {211state->array_state = NULL;212free(arrays);213__glXSetError(gc, GL_OUT_OF_MEMORY);214return;215}216217arrays->arrays[0].data_type = GL_FLOAT;218arrays->arrays[0].count = 3;219arrays->arrays[0].key = GL_NORMAL_ARRAY;220arrays->arrays[0].normalized = GL_TRUE;221arrays->arrays[0].old_DrawArrays_possible = GL_TRUE;222223arrays->arrays[1].data_type = GL_FLOAT;224arrays->arrays[1].count = 4;225arrays->arrays[1].key = GL_COLOR_ARRAY;226arrays->arrays[1].normalized = GL_TRUE;227arrays->arrays[1].old_DrawArrays_possible = GL_TRUE;228229arrays->arrays[2].data_type = GL_FLOAT;230arrays->arrays[2].count = 1;231arrays->arrays[2].key = GL_INDEX_ARRAY;232arrays->arrays[2].old_DrawArrays_possible = GL_TRUE;233234arrays->arrays[3].data_type = GL_UNSIGNED_BYTE;235arrays->arrays[3].count = 1;236arrays->arrays[3].key = GL_EDGE_FLAG_ARRAY;237arrays->arrays[3].old_DrawArrays_possible = GL_TRUE;238239for (i = 0; i < texture_units; i++) {240arrays->arrays[4 + i].data_type = GL_FLOAT;241arrays->arrays[4 + i].count = 4;242arrays->arrays[4 + i].key = GL_TEXTURE_COORD_ARRAY;243244arrays->arrays[4 + i].old_DrawArrays_possible = (i == 0);245arrays->arrays[4 + i].index = i;246}247248i = 4 + texture_units;249250if (got_fog) {251arrays->arrays[i].data_type = GL_FLOAT;252arrays->arrays[i].count = 1;253arrays->arrays[i].key = GL_FOG_COORDINATE_ARRAY;254arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;255i++;256}257258if (got_secondary_color) {259arrays->arrays[i].data_type = GL_FLOAT;260arrays->arrays[i].count = 3;261arrays->arrays[i].key = GL_SECONDARY_COLOR_ARRAY;262arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;263arrays->arrays[i].normalized = GL_TRUE;264i++;265}266267268for (j = 0; j < vertex_program_attribs; j++) {269const unsigned idx = (vertex_program_attribs - (j + 1));270271272arrays->arrays[idx + i].data_type = GL_FLOAT;273arrays->arrays[idx + i].count = 4;274arrays->arrays[idx + i].key = GL_VERTEX_ATTRIB_ARRAY_POINTER;275276arrays->arrays[idx + i].old_DrawArrays_possible = 0;277arrays->arrays[idx + i].index = idx;278}279280i += vertex_program_attribs;281282283/* Vertex array *must* be last because of the way that284* emit_DrawArrays_none works.285*/286287arrays->arrays[i].data_type = GL_FLOAT;288arrays->arrays[i].count = 4;289arrays->arrays[i].key = GL_VERTEX_ARRAY;290arrays->arrays[i].old_DrawArrays_possible = GL_TRUE;291292assert((i + 1) == arrays->num_arrays);293294arrays->stack_index = 0;295arrays->stack = malloc(sizeof(struct array_stack_state)296* arrays->num_arrays297* __GL_CLIENT_ATTRIB_STACK_DEPTH);298299if (arrays->stack == NULL) {300state->array_state = NULL;301free(arrays->arrays);302free(arrays);303__glXSetError(gc, GL_OUT_OF_MEMORY);304return;305}306}307308309/**310* Calculate the size of a single vertex for the "none" protocol. This is311* essentially the size of all the immediate-mode commands required to312* implement the enabled vertex arrays.313*/314static size_t315calculate_single_vertex_size_none(const struct array_state_vector *arrays)316{317size_t single_vertex_size = 0;318unsigned i;319320321for (i = 0; i < arrays->num_arrays; i++) {322if (arrays->arrays[i].enabled) {323single_vertex_size += arrays->arrays[i].header[0];324}325}326327return single_vertex_size;328}329330331/**332* Emit a single element using non-DrawArrays protocol.333*/334GLubyte *335emit_element_none(GLubyte * dst,336const struct array_state_vector * arrays, unsigned index)337{338unsigned i;339340341for (i = 0; i < arrays->num_arrays; i++) {342if (arrays->arrays[i].enabled) {343const size_t offset = index * arrays->arrays[i].true_stride;344345/* The generic attributes can have more data than is in the346* elements. This is because a vertex array can be a 2 element,347* normalized, unsigned short, but the "closest" immediate mode348* protocol is for a 4Nus. Since the sizes are small, the349* performance impact on modern processors should be negligible.350*/351(void) memset(dst, 0, arrays->arrays[i].header[0]);352353(void) memcpy(dst, arrays->arrays[i].header, 4);354355dst += 4;356357if (arrays->arrays[i].key == GL_TEXTURE_COORD_ARRAY &&358arrays->arrays[i].index > 0) {359/* Multi-texture coordinate arrays require the texture target360* to be sent. For doubles it is after the data, for everything361* else it is before.362*/363GLenum texture = arrays->arrays[i].index + GL_TEXTURE0;364if (arrays->arrays[i].data_type == GL_DOUBLE) {365(void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,366arrays->arrays[i].element_size);367dst += arrays->arrays[i].element_size;368(void) memcpy(dst, &texture, 4);369dst += 4;370} else {371(void) memcpy(dst, &texture, 4);372dst += 4;373(void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,374arrays->arrays[i].element_size);375dst += __GLX_PAD(arrays->arrays[i].element_size);376}377} else if (arrays->arrays[i].key == GL_VERTEX_ATTRIB_ARRAY_POINTER) {378/* Vertex attribute data requires the index sent first.379*/380(void) memcpy(dst, &arrays->arrays[i].index, 4);381dst += 4;382(void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,383arrays->arrays[i].element_size);384dst += __GLX_PAD(arrays->arrays[i].element_size);385} else {386(void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,387arrays->arrays[i].element_size);388dst += __GLX_PAD(arrays->arrays[i].element_size);389}390}391}392393return dst;394}395396397/**398* Emit a single element using "old" DrawArrays protocol from399* EXT_vertex_arrays / OpenGL 1.1.400*/401GLubyte *402emit_element_old(GLubyte * dst,403const struct array_state_vector * arrays, unsigned index)404{405unsigned i;406407408for (i = 0; i < arrays->num_arrays; i++) {409if (arrays->arrays[i].enabled) {410const size_t offset = index * arrays->arrays[i].true_stride;411412(void) memcpy(dst, ((GLubyte *) arrays->arrays[i].data) + offset,413arrays->arrays[i].element_size);414415dst += __GLX_PAD(arrays->arrays[i].element_size);416}417}418419return dst;420}421422423struct array_state *424get_array_entry(const struct array_state_vector *arrays,425GLenum key, unsigned index)426{427unsigned i;428429for (i = 0; i < arrays->num_arrays; i++) {430if ((arrays->arrays[i].key == key)431&& (arrays->arrays[i].index == index)) {432return &arrays->arrays[i];433}434}435436return NULL;437}438439440static GLboolean441allocate_array_info_cache(struct array_state_vector *arrays,442size_t required_size)443{444#define MAX_HEADER_SIZE 20445if (arrays->array_info_cache_buffer_size < required_size) {446GLubyte *temp = realloc(arrays->array_info_cache_base,447required_size + MAX_HEADER_SIZE);448449if (temp == NULL) {450return GL_FALSE;451}452453arrays->array_info_cache_base = temp;454arrays->array_info_cache = temp + MAX_HEADER_SIZE;455arrays->array_info_cache_buffer_size = required_size;456}457458arrays->array_info_cache_size = required_size;459return GL_TRUE;460}461462463/**464*/465void466fill_array_info_cache(struct array_state_vector *arrays)467{468GLboolean old_DrawArrays_possible;469unsigned i;470471472/* Determine how many arrays are enabled.473*/474475arrays->enabled_client_array_count = 0;476old_DrawArrays_possible = arrays->old_DrawArrays_possible;477for (i = 0; i < arrays->num_arrays; i++) {478if (arrays->arrays[i].enabled) {479arrays->enabled_client_array_count++;480old_DrawArrays_possible &= arrays->arrays[i].old_DrawArrays_possible;481}482}483484if (arrays->new_DrawArrays_possible) {485assert(!arrays->new_DrawArrays_possible);486}487else if (old_DrawArrays_possible) {488const size_t required_size = arrays->enabled_client_array_count * 12;489uint32_t *info;490491492if (!allocate_array_info_cache(arrays, required_size)) {493return;494}495496497info = (uint32_t *) arrays->array_info_cache;498for (i = 0; i < arrays->num_arrays; i++) {499if (arrays->arrays[i].enabled) {500*(info++) = arrays->arrays[i].data_type;501*(info++) = arrays->arrays[i].count;502*(info++) = arrays->arrays[i].key;503}504}505506arrays->DrawArrays = emit_DrawArrays_old;507arrays->DrawElements = emit_DrawElements_old;508}509else {510arrays->DrawArrays = emit_DrawArrays_none;511arrays->DrawElements = emit_DrawElements_none;512}513514arrays->array_info_cache_valid = GL_TRUE;515}516517518/**519* Emit a \c glDrawArrays command using the "none" protocol. That is,520* emit immediate-mode commands that are equivalent to the requiested521* \c glDrawArrays command. This is used with servers that don't support522* the OpenGL 1.1 / EXT_vertex_arrays DrawArrays protocol or in cases where523* vertex state is enabled that is not compatible with that protocol.524*/525void526emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count)527{528struct glx_context *gc = __glXGetCurrentContext();529const __GLXattribute *state =530(const __GLXattribute *) (gc->client_state_private);531struct array_state_vector *arrays = state->array_state;532533size_t single_vertex_size;534GLubyte *pc;535unsigned i;536static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin };537static const uint16_t end_cmd[2] = { 4, X_GLrop_End };538539540single_vertex_size = calculate_single_vertex_size_none(arrays);541542pc = gc->pc;543544(void) memcpy(pc, begin_cmd, 4);545*(int *) (pc + 4) = mode;546547pc += 8;548549for (i = 0; i < count; i++) {550if ((pc + single_vertex_size) >= gc->bufEnd) {551pc = __glXFlushRenderBuffer(gc, pc);552}553554pc = emit_element_none(pc, arrays, first + i);555}556557if ((pc + 4) >= gc->bufEnd) {558pc = __glXFlushRenderBuffer(gc, pc);559}560561(void) memcpy(pc, end_cmd, 4);562pc += 4;563564gc->pc = pc;565if (gc->pc > gc->limit) {566(void) __glXFlushRenderBuffer(gc, gc->pc);567}568}569570571/**572* Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays573* protocol.574*575* \param gc GLX context.576* \param arrays Array state.577* \param elements_per_request Location to store the number of elements that578* can fit in a single Render / RenderLarge579* command.580* \param total_request Total number of requests for a RenderLarge581* command. If a Render command is used, this582* will be zero.583* \param mode Drawing mode.584* \param count Number of vertices.585*586* \returns587* A pointer to the buffer for array data.588*/589static GLubyte *590emit_DrawArrays_header_old(struct glx_context * gc,591struct array_state_vector *arrays,592size_t * elements_per_request,593unsigned int *total_requests,594GLenum mode, GLsizei count)595{596size_t command_size;597size_t single_vertex_size;598const unsigned header_size = 16;599unsigned i;600GLubyte *pc;601602603/* Determine the size of the whole command. This includes the header,604* the ARRAY_INFO data and the array data. Once this size is calculated,605* it will be known whether a Render or RenderLarge command is needed.606*/607608single_vertex_size = 0;609for (i = 0; i < arrays->num_arrays; i++) {610if (arrays->arrays[i].enabled) {611single_vertex_size += __GLX_PAD(arrays->arrays[i].element_size);612}613}614615command_size = arrays->array_info_cache_size + header_size616+ (single_vertex_size * count);617618619/* Write the header for either a Render command or a RenderLarge620* command. After the header is written, write the ARRAY_INFO data.621*/622623if (command_size > gc->maxSmallRenderCommandSize) {624/* maxSize is the maximum amount of data can be stuffed into a single625* packet. sz_xGLXRenderReq is added because bufSize is the maximum626* packet size minus sz_xGLXRenderReq.627*/628const size_t maxSize = (gc->bufSize + sz_xGLXRenderReq)629- sz_xGLXRenderLargeReq;630unsigned vertex_requests;631632633/* Calculate the number of data packets that will be required to send634* the whole command. To do this, the number of verticies that635* will fit in a single buffer must be calculated.636*637* The important value here is elements_per_request. This is the638* number of complete array elements that will fit in a single639* buffer. There may be some wasted space at the end of the buffer,640* but splitting elements across buffer boundries would be painful.641*/642643elements_per_request[0] = maxSize / single_vertex_size;644645vertex_requests = (count + elements_per_request[0] - 1)646/ elements_per_request[0];647648*total_requests = vertex_requests + 1;649650651__glXFlushRenderBuffer(gc, gc->pc);652653command_size += 4;654655pc = ((GLubyte *) arrays->array_info_cache) - (header_size + 4);656*(uint32_t *) (pc + 0) = command_size;657*(uint32_t *) (pc + 4) = X_GLrop_DrawArrays;658*(uint32_t *) (pc + 8) = count;659*(uint32_t *) (pc + 12) = arrays->enabled_client_array_count;660*(uint32_t *) (pc + 16) = mode;661662__glXSendLargeChunk(gc, 1, *total_requests, pc,663header_size + 4 + arrays->array_info_cache_size);664665pc = gc->pc;666}667else {668if ((gc->pc + command_size) >= gc->bufEnd) {669(void) __glXFlushRenderBuffer(gc, gc->pc);670}671672pc = gc->pc;673*(uint16_t *) (pc + 0) = command_size;674*(uint16_t *) (pc + 2) = X_GLrop_DrawArrays;675*(uint32_t *) (pc + 4) = count;676*(uint32_t *) (pc + 8) = arrays->enabled_client_array_count;677*(uint32_t *) (pc + 12) = mode;678679pc += header_size;680681(void) memcpy(pc, arrays->array_info_cache,682arrays->array_info_cache_size);683pc += arrays->array_info_cache_size;684685*elements_per_request = count;686*total_requests = 0;687}688689690return pc;691}692693694/**695*/696void697emit_DrawArrays_old(GLenum mode, GLint first, GLsizei count)698{699struct glx_context *gc = __glXGetCurrentContext();700const __GLXattribute *state =701(const __GLXattribute *) (gc->client_state_private);702struct array_state_vector *arrays = state->array_state;703704GLubyte *pc;705size_t elements_per_request;706unsigned total_requests = 0;707unsigned i;708size_t total_sent = 0;709710711pc = emit_DrawArrays_header_old(gc, arrays, &elements_per_request,712&total_requests, mode, count);713714715/* Write the arrays.716*/717718if (total_requests == 0) {719assert(elements_per_request >= count);720721for (i = 0; i < count; i++) {722pc = emit_element_old(pc, arrays, i + first);723}724725assert(pc <= gc->bufEnd);726727gc->pc = pc;728if (gc->pc > gc->limit) {729(void) __glXFlushRenderBuffer(gc, gc->pc);730}731}732else {733unsigned req;734735736for (req = 2; req <= total_requests; req++) {737if (count < elements_per_request) {738elements_per_request = count;739}740741pc = gc->pc;742for (i = 0; i < elements_per_request; i++) {743pc = emit_element_old(pc, arrays, i + first);744}745746first += elements_per_request;747748total_sent += (size_t) (pc - gc->pc);749__glXSendLargeChunk(gc, req, total_requests, gc->pc, pc - gc->pc);750751count -= elements_per_request;752}753}754}755756757void758emit_DrawElements_none(GLenum mode, GLsizei count, GLenum type,759const GLvoid * indices)760{761struct glx_context *gc = __glXGetCurrentContext();762const __GLXattribute *state =763(const __GLXattribute *) (gc->client_state_private);764struct array_state_vector *arrays = state->array_state;765static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin };766static const uint16_t end_cmd[2] = { 4, X_GLrop_End };767768GLubyte *pc;769size_t single_vertex_size;770unsigned i;771772773single_vertex_size = calculate_single_vertex_size_none(arrays);774775776if ((gc->pc + single_vertex_size) >= gc->bufEnd) {777gc->pc = __glXFlushRenderBuffer(gc, gc->pc);778}779780pc = gc->pc;781782(void) memcpy(pc, begin_cmd, 4);783*(int *) (pc + 4) = mode;784785pc += 8;786787for (i = 0; i < count; i++) {788unsigned index = 0;789790if ((pc + single_vertex_size) >= gc->bufEnd) {791pc = __glXFlushRenderBuffer(gc, pc);792}793794switch (type) {795case GL_UNSIGNED_INT:796index = (unsigned) (((GLuint *) indices)[i]);797break;798case GL_UNSIGNED_SHORT:799index = (unsigned) (((GLushort *) indices)[i]);800break;801case GL_UNSIGNED_BYTE:802index = (unsigned) (((GLubyte *) indices)[i]);803break;804}805pc = emit_element_none(pc, arrays, index);806}807808if ((pc + 4) >= gc->bufEnd) {809pc = __glXFlushRenderBuffer(gc, pc);810}811812(void) memcpy(pc, end_cmd, 4);813pc += 4;814815gc->pc = pc;816if (gc->pc > gc->limit) {817(void) __glXFlushRenderBuffer(gc, gc->pc);818}819}820821822/**823*/824void825emit_DrawElements_old(GLenum mode, GLsizei count, GLenum type,826const GLvoid * indices)827{828struct glx_context *gc = __glXGetCurrentContext();829const __GLXattribute *state =830(const __GLXattribute *) (gc->client_state_private);831struct array_state_vector *arrays = state->array_state;832833GLubyte *pc;834size_t elements_per_request;835unsigned total_requests = 0;836unsigned i;837unsigned req;838unsigned req_element = 0;839840841pc = emit_DrawArrays_header_old(gc, arrays, &elements_per_request,842&total_requests, mode, count);843844845/* Write the arrays.846*/847848req = 2;849while (count > 0) {850if (count < elements_per_request) {851elements_per_request = count;852}853854switch (type) {855case GL_UNSIGNED_INT:{856const GLuint *ui_ptr = (const GLuint *) indices + req_element;857858for (i = 0; i < elements_per_request; i++) {859const GLint index = (GLint) * (ui_ptr++);860pc = emit_element_old(pc, arrays, index);861}862break;863}864case GL_UNSIGNED_SHORT:{865const GLushort *us_ptr = (const GLushort *) indices + req_element;866867for (i = 0; i < elements_per_request; i++) {868const GLint index = (GLint) * (us_ptr++);869pc = emit_element_old(pc, arrays, index);870}871break;872}873case GL_UNSIGNED_BYTE:{874const GLubyte *ub_ptr = (const GLubyte *) indices + req_element;875876for (i = 0; i < elements_per_request; i++) {877const GLint index = (GLint) * (ub_ptr++);878pc = emit_element_old(pc, arrays, index);879}880break;881}882}883884if (total_requests != 0) {885__glXSendLargeChunk(gc, req, total_requests, gc->pc, pc - gc->pc);886pc = gc->pc;887req++;888}889890count -= elements_per_request;891req_element += elements_per_request;892}893894895assert((total_requests == 0) || ((req - 1) == total_requests));896897if (total_requests == 0) {898assert(pc <= gc->bufEnd);899900gc->pc = pc;901if (gc->pc > gc->limit) {902(void) __glXFlushRenderBuffer(gc, gc->pc);903}904}905}906907908/**909* Validate that the \c mode parameter to \c glDrawArrays, et. al. is valid.910* If it is not valid, then an error code is set in the GLX context.911*912* \returns913* \c GL_TRUE if the argument is valid, \c GL_FALSE if is not.914*/915static GLboolean916validate_mode(struct glx_context * gc, GLenum mode)917{918switch (mode) {919case GL_POINTS:920case GL_LINE_STRIP:921case GL_LINE_LOOP:922case GL_LINES:923case GL_TRIANGLE_STRIP:924case GL_TRIANGLE_FAN:925case GL_TRIANGLES:926case GL_QUAD_STRIP:927case GL_QUADS:928case GL_POLYGON:929break;930default:931__glXSetError(gc, GL_INVALID_ENUM);932return GL_FALSE;933}934935return GL_TRUE;936}937938939/**940* Validate that the \c count parameter to \c glDrawArrays, et. al. is valid.941* A value less than zero is invalid and will result in \c GL_INVALID_VALUE942* being set. A value of zero will not result in an error being set, but943* will result in \c GL_FALSE being returned.944*945* \returns946* \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not.947*/948static GLboolean949validate_count(struct glx_context * gc, GLsizei count)950{951if (count < 0) {952__glXSetError(gc, GL_INVALID_VALUE);953}954955return (count > 0);956}957958959/**960* Validate that the \c type parameter to \c glDrawElements, et. al. is961* valid. Only \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, and962* \c GL_UNSIGNED_INT are valid.963*964* \returns965* \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not.966*/967static GLboolean968validate_type(struct glx_context * gc, GLenum type)969{970switch (type) {971case GL_UNSIGNED_INT:972case GL_UNSIGNED_SHORT:973case GL_UNSIGNED_BYTE:974return GL_TRUE;975default:976__glXSetError(gc, GL_INVALID_ENUM);977return GL_FALSE;978}979}980981982void983__indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count)984{985struct glx_context *gc = __glXGetCurrentContext();986const __GLXattribute *state =987(const __GLXattribute *) (gc->client_state_private);988struct array_state_vector *arrays = state->array_state;989990991if (validate_mode(gc, mode) && validate_count(gc, count)) {992if (!arrays->array_info_cache_valid) {993fill_array_info_cache(arrays);994}995996arrays->DrawArrays(mode, first, count);997}998}99910001001void1002__indirect_glArrayElement(GLint index)1003{1004struct glx_context *gc = __glXGetCurrentContext();1005const __GLXattribute *state =1006(const __GLXattribute *) (gc->client_state_private);1007struct array_state_vector *arrays = state->array_state;10081009size_t single_vertex_size;101010111012single_vertex_size = calculate_single_vertex_size_none(arrays);10131014if ((gc->pc + single_vertex_size) >= gc->bufEnd) {1015gc->pc = __glXFlushRenderBuffer(gc, gc->pc);1016}10171018gc->pc = emit_element_none(gc->pc, arrays, index);10191020if (gc->pc > gc->limit) {1021(void) __glXFlushRenderBuffer(gc, gc->pc);1022}1023}102410251026void1027__indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type,1028const GLvoid * indices)1029{1030struct glx_context *gc = __glXGetCurrentContext();1031const __GLXattribute *state =1032(const __GLXattribute *) (gc->client_state_private);1033struct array_state_vector *arrays = state->array_state;103410351036if (validate_mode(gc, mode) && validate_count(gc, count)1037&& validate_type(gc, type)) {1038if (!arrays->array_info_cache_valid) {1039fill_array_info_cache(arrays);1040}10411042arrays->DrawElements(mode, count, type, indices);1043}1044}104510461047void1048__indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,1049GLsizei count, GLenum type,1050const GLvoid * indices)1051{1052struct glx_context *gc = __glXGetCurrentContext();1053const __GLXattribute *state =1054(const __GLXattribute *) (gc->client_state_private);1055struct array_state_vector *arrays = state->array_state;105610571058if (validate_mode(gc, mode) && validate_count(gc, count)1059&& validate_type(gc, type)) {1060if (end < start) {1061__glXSetError(gc, GL_INVALID_VALUE);1062return;1063}10641065if (!arrays->array_info_cache_valid) {1066fill_array_info_cache(arrays);1067}10681069arrays->DrawElements(mode, count, type, indices);1070}1071}107210731074void1075__indirect_glMultiDrawArrays(GLenum mode, const GLint *first,1076const GLsizei *count, GLsizei primcount)1077{1078struct glx_context *gc = __glXGetCurrentContext();1079const __GLXattribute *state =1080(const __GLXattribute *) (gc->client_state_private);1081struct array_state_vector *arrays = state->array_state;1082GLsizei i;108310841085if (validate_mode(gc, mode)) {1086if (!arrays->array_info_cache_valid) {1087fill_array_info_cache(arrays);1088}10891090for (i = 0; i < primcount; i++) {1091if (validate_count(gc, count[i])) {1092arrays->DrawArrays(mode, first[i], count[i]);1093}1094}1095}1096}109710981099void1100__indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count,1101GLenum type, const GLvoid * const * indices,1102GLsizei primcount)1103{1104struct glx_context *gc = __glXGetCurrentContext();1105const __GLXattribute *state =1106(const __GLXattribute *) (gc->client_state_private);1107struct array_state_vector *arrays = state->array_state;1108GLsizei i;110911101111if (validate_mode(gc, mode) && validate_type(gc, type)) {1112if (!arrays->array_info_cache_valid) {1113fill_array_info_cache(arrays);1114}11151116for (i = 0; i < primcount; i++) {1117if (validate_count(gc, count[i])) {1118arrays->DrawElements(mode, count[i], type, indices[i]);1119}1120}1121}1122}112311241125/* The HDR_SIZE macro argument is the command header size (4 bytes)1126* plus any additional index word e.g. for texture units or vertex1127* attributes.1128*/1129#define COMMON_ARRAY_DATA_INIT(a, PTR, TYPE, STRIDE, COUNT, NORMALIZED, HDR_SIZE, OPCODE) \1130do { \1131(a)->data = PTR; \1132(a)->data_type = TYPE; \1133(a)->user_stride = STRIDE; \1134(a)->count = COUNT; \1135(a)->normalized = NORMALIZED; \1136\1137(a)->element_size = __glXTypeSize( TYPE ) * COUNT; \1138(a)->true_stride = (STRIDE == 0) \1139? (a)->element_size : STRIDE; \1140\1141(a)->header[0] = __GLX_PAD(HDR_SIZE + (a)->element_size); \1142(a)->header[1] = OPCODE; \1143} while(0)114411451146void1147__indirect_glVertexPointer(GLint size, GLenum type, GLsizei stride,1148const GLvoid * pointer)1149{1150static const uint16_t short_ops[5] = {11510, 0, X_GLrop_Vertex2sv, X_GLrop_Vertex3sv, X_GLrop_Vertex4sv1152};1153static const uint16_t int_ops[5] = {11540, 0, X_GLrop_Vertex2iv, X_GLrop_Vertex3iv, X_GLrop_Vertex4iv1155};1156static const uint16_t float_ops[5] = {11570, 0, X_GLrop_Vertex2fv, X_GLrop_Vertex3fv, X_GLrop_Vertex4fv1158};1159static const uint16_t double_ops[5] = {11600, 0, X_GLrop_Vertex2dv, X_GLrop_Vertex3dv, X_GLrop_Vertex4dv1161};1162uint16_t opcode;1163struct glx_context *gc = __glXGetCurrentContext();1164__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1165struct array_state_vector *arrays = state->array_state;1166struct array_state *a;116711681169if (size < 2 || size > 4 || stride < 0) {1170__glXSetError(gc, GL_INVALID_VALUE);1171return;1172}11731174switch (type) {1175case GL_SHORT:1176opcode = short_ops[size];1177break;1178case GL_INT:1179opcode = int_ops[size];1180break;1181case GL_FLOAT:1182opcode = float_ops[size];1183break;1184case GL_DOUBLE:1185opcode = double_ops[size];1186break;1187default:1188__glXSetError(gc, GL_INVALID_ENUM);1189return;1190}11911192a = get_array_entry(arrays, GL_VERTEX_ARRAY, 0);1193assert(a != NULL);1194COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_FALSE, 4,1195opcode);11961197if (a->enabled) {1198arrays->array_info_cache_valid = GL_FALSE;1199}1200}120112021203void1204__indirect_glNormalPointer(GLenum type, GLsizei stride,1205const GLvoid * pointer)1206{1207uint16_t opcode;1208struct glx_context *gc = __glXGetCurrentContext();1209__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1210struct array_state_vector *arrays = state->array_state;1211struct array_state *a;121212131214if (stride < 0) {1215__glXSetError(gc, GL_INVALID_VALUE);1216return;1217}12181219switch (type) {1220case GL_BYTE:1221opcode = X_GLrop_Normal3bv;1222break;1223case GL_SHORT:1224opcode = X_GLrop_Normal3sv;1225break;1226case GL_INT:1227opcode = X_GLrop_Normal3iv;1228break;1229case GL_FLOAT:1230opcode = X_GLrop_Normal3fv;1231break;1232case GL_DOUBLE:1233opcode = X_GLrop_Normal3dv;1234break;1235default:1236__glXSetError(gc, GL_INVALID_ENUM);1237return;1238}12391240a = get_array_entry(arrays, GL_NORMAL_ARRAY, 0);1241assert(a != NULL);1242COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, 3, GL_TRUE, 4, opcode);12431244if (a->enabled) {1245arrays->array_info_cache_valid = GL_FALSE;1246}1247}124812491250void1251__indirect_glColorPointer(GLint size, GLenum type, GLsizei stride,1252const GLvoid * pointer)1253{1254static const uint16_t byte_ops[5] = {12550, 0, 0, X_GLrop_Color3bv, X_GLrop_Color4bv1256};1257static const uint16_t ubyte_ops[5] = {12580, 0, 0, X_GLrop_Color3ubv, X_GLrop_Color4ubv1259};1260static const uint16_t short_ops[5] = {12610, 0, 0, X_GLrop_Color3sv, X_GLrop_Color4sv1262};1263static const uint16_t ushort_ops[5] = {12640, 0, 0, X_GLrop_Color3usv, X_GLrop_Color4usv1265};1266static const uint16_t int_ops[5] = {12670, 0, 0, X_GLrop_Color3iv, X_GLrop_Color4iv1268};1269static const uint16_t uint_ops[5] = {12700, 0, 0, X_GLrop_Color3uiv, X_GLrop_Color4uiv1271};1272static const uint16_t float_ops[5] = {12730, 0, 0, X_GLrop_Color3fv, X_GLrop_Color4fv1274};1275static const uint16_t double_ops[5] = {12760, 0, 0, X_GLrop_Color3dv, X_GLrop_Color4dv1277};1278uint16_t opcode;1279struct glx_context *gc = __glXGetCurrentContext();1280__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1281struct array_state_vector *arrays = state->array_state;1282struct array_state *a;128312841285if (size < 3 || size > 4 || stride < 0) {1286__glXSetError(gc, GL_INVALID_VALUE);1287return;1288}12891290switch (type) {1291case GL_BYTE:1292opcode = byte_ops[size];1293break;1294case GL_UNSIGNED_BYTE:1295opcode = ubyte_ops[size];1296break;1297case GL_SHORT:1298opcode = short_ops[size];1299break;1300case GL_UNSIGNED_SHORT:1301opcode = ushort_ops[size];1302break;1303case GL_INT:1304opcode = int_ops[size];1305break;1306case GL_UNSIGNED_INT:1307opcode = uint_ops[size];1308break;1309case GL_FLOAT:1310opcode = float_ops[size];1311break;1312case GL_DOUBLE:1313opcode = double_ops[size];1314break;1315default:1316__glXSetError(gc, GL_INVALID_ENUM);1317return;1318}13191320a = get_array_entry(arrays, GL_COLOR_ARRAY, 0);1321assert(a != NULL);1322COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_TRUE, 4, opcode);13231324if (a->enabled) {1325arrays->array_info_cache_valid = GL_FALSE;1326}1327}132813291330void1331__indirect_glIndexPointer(GLenum type, GLsizei stride, const GLvoid * pointer)1332{1333uint16_t opcode;1334struct glx_context *gc = __glXGetCurrentContext();1335__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1336struct array_state_vector *arrays = state->array_state;1337struct array_state *a;133813391340if (stride < 0) {1341__glXSetError(gc, GL_INVALID_VALUE);1342return;1343}13441345switch (type) {1346case GL_UNSIGNED_BYTE:1347opcode = X_GLrop_Indexubv;1348break;1349case GL_SHORT:1350opcode = X_GLrop_Indexsv;1351break;1352case GL_INT:1353opcode = X_GLrop_Indexiv;1354break;1355case GL_FLOAT:1356opcode = X_GLrop_Indexfv;1357break;1358case GL_DOUBLE:1359opcode = X_GLrop_Indexdv;1360break;1361default:1362__glXSetError(gc, GL_INVALID_ENUM);1363return;1364}13651366a = get_array_entry(arrays, GL_INDEX_ARRAY, 0);1367assert(a != NULL);1368COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, 1, GL_FALSE, 4, opcode);13691370if (a->enabled) {1371arrays->array_info_cache_valid = GL_FALSE;1372}1373}137413751376void1377__indirect_glEdgeFlagPointer(GLsizei stride, const GLvoid * pointer)1378{1379struct glx_context *gc = __glXGetCurrentContext();1380__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1381struct array_state_vector *arrays = state->array_state;1382struct array_state *a;138313841385if (stride < 0) {1386__glXSetError(gc, GL_INVALID_VALUE);1387return;1388}138913901391a = get_array_entry(arrays, GL_EDGE_FLAG_ARRAY, 0);1392assert(a != NULL);1393COMMON_ARRAY_DATA_INIT(a, pointer, GL_UNSIGNED_BYTE, stride, 1, GL_FALSE,13944, X_GLrop_EdgeFlagv);13951396if (a->enabled) {1397arrays->array_info_cache_valid = GL_FALSE;1398}1399}140014011402void1403__indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride,1404const GLvoid * pointer)1405{1406static const uint16_t short_ops[5] = {14070, X_GLrop_TexCoord1sv, X_GLrop_TexCoord2sv, X_GLrop_TexCoord3sv,1408X_GLrop_TexCoord4sv1409};1410static const uint16_t int_ops[5] = {14110, X_GLrop_TexCoord1iv, X_GLrop_TexCoord2iv, X_GLrop_TexCoord3iv,1412X_GLrop_TexCoord4iv1413};1414static const uint16_t float_ops[5] = {14150, X_GLrop_TexCoord1fv, X_GLrop_TexCoord2fv, X_GLrop_TexCoord3fv,1416X_GLrop_TexCoord4fv1417};1418static const uint16_t double_ops[5] = {14190, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2dv, X_GLrop_TexCoord3dv,1420X_GLrop_TexCoord4dv1421};14221423static const uint16_t mshort_ops[5] = {14240, X_GLrop_MultiTexCoord1svARB, X_GLrop_MultiTexCoord2svARB,1425X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB1426};1427static const uint16_t mint_ops[5] = {14280, X_GLrop_MultiTexCoord1ivARB, X_GLrop_MultiTexCoord2ivARB,1429X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB1430};1431static const uint16_t mfloat_ops[5] = {14320, X_GLrop_MultiTexCoord1fvARB, X_GLrop_MultiTexCoord2fvARB,1433X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB1434};1435static const uint16_t mdouble_ops[5] = {14360, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2dvARB,1437X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB1438};14391440uint16_t opcode;1441struct glx_context *gc = __glXGetCurrentContext();1442__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1443struct array_state_vector *arrays = state->array_state;1444struct array_state *a;1445unsigned header_size;1446unsigned index;144714481449if (size < 1 || size > 4 || stride < 0) {1450__glXSetError(gc, GL_INVALID_VALUE);1451return;1452}14531454index = arrays->active_texture_unit;1455if (index == 0) {1456switch (type) {1457case GL_SHORT:1458opcode = short_ops[size];1459break;1460case GL_INT:1461opcode = int_ops[size];1462break;1463case GL_FLOAT:1464opcode = float_ops[size];1465break;1466case GL_DOUBLE:1467opcode = double_ops[size];1468break;1469default:1470__glXSetError(gc, GL_INVALID_ENUM);1471return;1472}14731474header_size = 4;1475}1476else {1477switch (type) {1478case GL_SHORT:1479opcode = mshort_ops[size];1480break;1481case GL_INT:1482opcode = mint_ops[size];1483break;1484case GL_FLOAT:1485opcode = mfloat_ops[size];1486break;1487case GL_DOUBLE:1488opcode = mdouble_ops[size];1489break;1490default:1491__glXSetError(gc, GL_INVALID_ENUM);1492return;1493}14941495header_size = 8;1496}14971498a = get_array_entry(arrays, GL_TEXTURE_COORD_ARRAY, index);1499assert(a != NULL);1500COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_FALSE,1501header_size, opcode);15021503if (a->enabled) {1504arrays->array_info_cache_valid = GL_FALSE;1505}1506}150715081509void1510__indirect_glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride,1511const GLvoid * pointer)1512{1513uint16_t opcode;1514struct glx_context *gc = __glXGetCurrentContext();1515__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1516struct array_state_vector *arrays = state->array_state;1517struct array_state *a;151815191520if (size != 3 || stride < 0) {1521__glXSetError(gc, GL_INVALID_VALUE);1522return;1523}15241525switch (type) {1526case GL_BYTE:1527opcode = 4126;1528break;1529case GL_UNSIGNED_BYTE:1530opcode = 4131;1531break;1532case GL_SHORT:1533opcode = 4127;1534break;1535case GL_UNSIGNED_SHORT:1536opcode = 4132;1537break;1538case GL_INT:1539opcode = 4128;1540break;1541case GL_UNSIGNED_INT:1542opcode = 4133;1543break;1544case GL_FLOAT:1545opcode = 4129;1546break;1547case GL_DOUBLE:1548opcode = 4130;1549break;1550default:1551__glXSetError(gc, GL_INVALID_ENUM);1552return;1553}15541555a = get_array_entry(arrays, GL_SECONDARY_COLOR_ARRAY, 0);1556if (a == NULL) {1557__glXSetError(gc, GL_INVALID_OPERATION);1558return;1559}15601561COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, GL_TRUE, 4, opcode);15621563if (a->enabled) {1564arrays->array_info_cache_valid = GL_FALSE;1565}1566}156715681569void1570__indirect_glFogCoordPointer(GLenum type, GLsizei stride,1571const GLvoid * pointer)1572{1573uint16_t opcode;1574struct glx_context *gc = __glXGetCurrentContext();1575__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1576struct array_state_vector *arrays = state->array_state;1577struct array_state *a;157815791580if (stride < 0) {1581__glXSetError(gc, GL_INVALID_VALUE);1582return;1583}15841585switch (type) {1586case GL_FLOAT:1587opcode = 4124;1588break;1589case GL_DOUBLE:1590opcode = 4125;1591break;1592default:1593__glXSetError(gc, GL_INVALID_ENUM);1594return;1595}15961597a = get_array_entry(arrays, GL_FOG_COORD_ARRAY, 0);1598if (a == NULL) {1599__glXSetError(gc, GL_INVALID_OPERATION);1600return;1601}16021603COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, 1, GL_FALSE, 4, opcode);16041605if (a->enabled) {1606arrays->array_info_cache_valid = GL_FALSE;1607}1608}160916101611void1612__indirect_glVertexAttribPointer(GLuint index, GLint size,1613GLenum type, GLboolean normalized,1614GLsizei stride, const GLvoid * pointer)1615{1616static const uint16_t short_ops[5] = {16170, X_GLrop_VertexAttrib1svARB, X_GLrop_VertexAttrib2svARB,1618X_GLrop_VertexAttrib3svARB, X_GLrop_VertexAttrib4svARB1619};1620static const uint16_t float_ops[5] = {16210, X_GLrop_VertexAttrib1fvARB, X_GLrop_VertexAttrib2fvARB,1622X_GLrop_VertexAttrib3fvARB, X_GLrop_VertexAttrib4fvARB1623};1624static const uint16_t double_ops[5] = {16250, X_GLrop_VertexAttrib1dvARB, X_GLrop_VertexAttrib2dvARB,1626X_GLrop_VertexAttrib3dvARB, X_GLrop_VertexAttrib4dvARB1627};16281629uint16_t opcode;1630struct glx_context *gc = __glXGetCurrentContext();1631__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);1632struct array_state_vector *arrays = state->array_state;1633struct array_state *a;1634unsigned true_immediate_count;1635unsigned true_immediate_size;163616371638if ((size < 1) || (size > 4) || (stride < 0)1639|| (index > arrays->num_vertex_program_attribs)) {1640__glXSetError(gc, GL_INVALID_VALUE);1641return;1642}16431644if (normalized && (type != GL_FLOAT) && (type != GL_DOUBLE)) {1645switch (type) {1646case GL_BYTE:1647opcode = X_GLrop_VertexAttrib4NbvARB;1648break;1649case GL_UNSIGNED_BYTE:1650opcode = X_GLrop_VertexAttrib4NubvARB;1651break;1652case GL_SHORT:1653opcode = X_GLrop_VertexAttrib4NsvARB;1654break;1655case GL_UNSIGNED_SHORT:1656opcode = X_GLrop_VertexAttrib4NusvARB;1657break;1658case GL_INT:1659opcode = X_GLrop_VertexAttrib4NivARB;1660break;1661case GL_UNSIGNED_INT:1662opcode = X_GLrop_VertexAttrib4NuivARB;1663break;1664default:1665__glXSetError(gc, GL_INVALID_ENUM);1666return;1667}16681669true_immediate_count = 4;1670}1671else {1672true_immediate_count = size;16731674switch (type) {1675case GL_BYTE:1676opcode = X_GLrop_VertexAttrib4bvARB;1677true_immediate_count = 4;1678break;1679case GL_UNSIGNED_BYTE:1680opcode = X_GLrop_VertexAttrib4ubvARB;1681true_immediate_count = 4;1682break;1683case GL_SHORT:1684opcode = short_ops[size];1685break;1686case GL_UNSIGNED_SHORT:1687opcode = X_GLrop_VertexAttrib4usvARB;1688true_immediate_count = 4;1689break;1690case GL_INT:1691opcode = X_GLrop_VertexAttrib4ivARB;1692true_immediate_count = 4;1693break;1694case GL_UNSIGNED_INT:1695opcode = X_GLrop_VertexAttrib4uivARB;1696true_immediate_count = 4;1697break;1698case GL_FLOAT:1699opcode = float_ops[size];1700break;1701case GL_DOUBLE:1702opcode = double_ops[size];1703break;1704default:1705__glXSetError(gc, GL_INVALID_ENUM);1706return;1707}1708}17091710a = get_array_entry(arrays, GL_VERTEX_ATTRIB_ARRAY_POINTER, index);1711if (a == NULL) {1712__glXSetError(gc, GL_INVALID_OPERATION);1713return;1714}17151716COMMON_ARRAY_DATA_INIT(a, pointer, type, stride, size, normalized, 8,1717opcode);17181719true_immediate_size = __glXTypeSize(type) * true_immediate_count;1720a->header[0] = __GLX_PAD(8 + true_immediate_size);17211722if (a->enabled) {1723arrays->array_info_cache_valid = GL_FALSE;1724}1725}172617271728/**1729* I don't have 100% confidence that this is correct. The different rules1730* about whether or not generic vertex attributes alias "classic" vertex1731* attributes (i.e., attrib1 ?= primary color) between ARB_vertex_program,1732* ARB_vertex_shader, and NV_vertex_program are a bit confusing. My1733* feeling is that the client-side doesn't have to worry about it. The1734* client just sends all the data to the server and lets the server deal1735* with it.1736*/1737void1738__indirect_glVertexAttribPointerNV(GLuint index, GLint size,1739GLenum type, GLsizei stride,1740const GLvoid * pointer)1741{1742struct glx_context *gc = __glXGetCurrentContext();1743GLboolean normalized = GL_FALSE;174417451746switch (type) {1747case GL_UNSIGNED_BYTE:1748if (size != 4) {1749__glXSetError(gc, GL_INVALID_VALUE);1750return;1751}1752normalized = GL_TRUE;1753FALLTHROUGH;1754case GL_SHORT:1755case GL_FLOAT:1756case GL_DOUBLE:1757__indirect_glVertexAttribPointer(index, size, type,1758normalized, stride, pointer);1759return;1760default:1761__glXSetError(gc, GL_INVALID_ENUM);1762return;1763}1764}176517661767void1768__indirect_glClientActiveTexture(GLenum texture)1769{1770struct glx_context *const gc = __glXGetCurrentContext();1771__GLXattribute *const state =1772(__GLXattribute *) (gc->client_state_private);1773struct array_state_vector *const arrays = state->array_state;1774const GLint unit = (GLint) texture - GL_TEXTURE0;177517761777if ((unit < 0) || (unit >= arrays->num_texture_units)) {1778__glXSetError(gc, GL_INVALID_ENUM);1779return;1780}17811782arrays->active_texture_unit = unit;1783}178417851786/**1787* Modify the enable state for the selected array1788*/1789GLboolean1790__glXSetArrayEnable(__GLXattribute * state, GLenum key, unsigned index,1791GLboolean enable)1792{1793struct array_state_vector *arrays = state->array_state;1794struct array_state *a;179517961797/* Texture coordinate arrays have an implict index set when the1798* application calls glClientActiveTexture.1799*/1800if (key == GL_TEXTURE_COORD_ARRAY) {1801index = arrays->active_texture_unit;1802}18031804a = get_array_entry(arrays, key, index);18051806if ((a != NULL) && (a->enabled != enable)) {1807a->enabled = enable;1808arrays->array_info_cache_valid = GL_FALSE;1809}18101811return (a != NULL);1812}181318141815void1816__glXArrayDisableAll(__GLXattribute * state)1817{1818struct array_state_vector *arrays = state->array_state;1819unsigned i;182018211822for (i = 0; i < arrays->num_arrays; i++) {1823arrays->arrays[i].enabled = GL_FALSE;1824}18251826arrays->array_info_cache_valid = GL_FALSE;1827}182818291830/**1831*/1832GLboolean1833__glXGetArrayEnable(const __GLXattribute * const state,1834GLenum key, unsigned index, GLintptr * dest)1835{1836const struct array_state_vector *arrays = state->array_state;1837const struct array_state *a =1838get_array_entry((struct array_state_vector *) arrays,1839key, index);18401841if (a != NULL) {1842*dest = (GLintptr) a->enabled;1843}18441845return (a != NULL);1846}184718481849/**1850*/1851GLboolean1852__glXGetArrayType(const __GLXattribute * const state,1853GLenum key, unsigned index, GLintptr * dest)1854{1855const struct array_state_vector *arrays = state->array_state;1856const struct array_state *a =1857get_array_entry((struct array_state_vector *) arrays,1858key, index);18591860if (a != NULL) {1861*dest = (GLintptr) a->data_type;1862}18631864return (a != NULL);1865}186618671868/**1869*/1870GLboolean1871__glXGetArraySize(const __GLXattribute * const state,1872GLenum key, unsigned index, GLintptr * dest)1873{1874const struct array_state_vector *arrays = state->array_state;1875const struct array_state *a =1876get_array_entry((struct array_state_vector *) arrays,1877key, index);18781879if (a != NULL) {1880*dest = (GLintptr) a->count;1881}18821883return (a != NULL);1884}188518861887/**1888*/1889GLboolean1890__glXGetArrayStride(const __GLXattribute * const state,1891GLenum key, unsigned index, GLintptr * dest)1892{1893const struct array_state_vector *arrays = state->array_state;1894const struct array_state *a =1895get_array_entry((struct array_state_vector *) arrays,1896key, index);18971898if (a != NULL) {1899*dest = (GLintptr) a->user_stride;1900}19011902return (a != NULL);1903}190419051906/**1907*/1908GLboolean1909__glXGetArrayPointer(const __GLXattribute * const state,1910GLenum key, unsigned index, void **dest)1911{1912const struct array_state_vector *arrays = state->array_state;1913const struct array_state *a =1914get_array_entry((struct array_state_vector *) arrays,1915key, index);191619171918if (a != NULL) {1919*dest = (void *) (a->data);1920}19211922return (a != NULL);1923}192419251926/**1927*/1928GLboolean1929__glXGetArrayNormalized(const __GLXattribute * const state,1930GLenum key, unsigned index, GLintptr * dest)1931{1932const struct array_state_vector *arrays = state->array_state;1933const struct array_state *a =1934get_array_entry((struct array_state_vector *) arrays,1935key, index);193619371938if (a != NULL) {1939*dest = (GLintptr) a->normalized;1940}19411942return (a != NULL);1943}194419451946/**1947*/1948GLuint1949__glXGetActiveTextureUnit(const __GLXattribute * const state)1950{1951return state->array_state->active_texture_unit;1952}195319541955void1956__glXPushArrayState(__GLXattribute * state)1957{1958struct array_state_vector *arrays = state->array_state;1959struct array_stack_state *stack =1960&arrays->stack[(arrays->stack_index * arrays->num_arrays)];1961unsigned i;19621963/* XXX are we pushing _all_ the necessary fields? */1964for (i = 0; i < arrays->num_arrays; i++) {1965stack[i].data = arrays->arrays[i].data;1966stack[i].data_type = arrays->arrays[i].data_type;1967stack[i].user_stride = arrays->arrays[i].user_stride;1968stack[i].count = arrays->arrays[i].count;1969stack[i].key = arrays->arrays[i].key;1970stack[i].index = arrays->arrays[i].index;1971stack[i].enabled = arrays->arrays[i].enabled;1972}19731974arrays->active_texture_unit_stack[arrays->stack_index] =1975arrays->active_texture_unit;19761977arrays->stack_index++;1978}197919801981void1982__glXPopArrayState(__GLXattribute * state)1983{1984struct array_state_vector *arrays = state->array_state;1985struct array_stack_state *stack;1986unsigned i;198719881989arrays->stack_index--;1990stack = &arrays->stack[(arrays->stack_index * arrays->num_arrays)];19911992for (i = 0; i < arrays->num_arrays; i++) {1993switch (stack[i].key) {1994case GL_NORMAL_ARRAY:1995__indirect_glNormalPointer(stack[i].data_type,1996stack[i].user_stride, stack[i].data);1997break;1998case GL_COLOR_ARRAY:1999__indirect_glColorPointer(stack[i].count,2000stack[i].data_type,2001stack[i].user_stride, stack[i].data);2002break;2003case GL_INDEX_ARRAY:2004__indirect_glIndexPointer(stack[i].data_type,2005stack[i].user_stride, stack[i].data);2006break;2007case GL_EDGE_FLAG_ARRAY:2008__indirect_glEdgeFlagPointer(stack[i].user_stride, stack[i].data);2009break;2010case GL_TEXTURE_COORD_ARRAY:2011arrays->active_texture_unit = stack[i].index;2012__indirect_glTexCoordPointer(stack[i].count,2013stack[i].data_type,2014stack[i].user_stride, stack[i].data);2015break;2016case GL_SECONDARY_COLOR_ARRAY:2017__indirect_glSecondaryColorPointer(stack[i].count,2018stack[i].data_type,2019stack[i].user_stride,2020stack[i].data);2021break;2022case GL_FOG_COORDINATE_ARRAY:2023__indirect_glFogCoordPointer(stack[i].data_type,2024stack[i].user_stride, stack[i].data);2025break;20262027}20282029__glXSetArrayEnable(state, stack[i].key, stack[i].index,2030stack[i].enabled);2031}20322033arrays->active_texture_unit =2034arrays->active_texture_unit_stack[arrays->stack_index];2035}203620372038