📄 indirect_vertex_array.c
字号:
else { arrays->DrawArrays = emit_DrawArrays_none; arrays->DrawElements = emit_DrawElements_none; } arrays->array_info_cache_valid = GL_TRUE;}/** * Emit a \c glDrawArrays command using the "none" protocol. That is, * emit immediate-mode commands that are equivalent to the requiested * \c glDrawArrays command. This is used with servers that don't support * the OpenGL 1.1 / EXT_vertex_arrays DrawArrays protocol or in cases where * vertex state is enabled that is not compatible with that protocol. */voidemit_DrawArrays_none( GLenum mode, GLint first, GLsizei count ){ __GLXcontext *gc = __glXGetCurrentContext(); const __GLXattribute * state = (const __GLXattribute *)(gc->client_state_private); struct array_state_vector * arrays = state->array_state; size_t single_vertex_size; GLubyte * pc; unsigned i; static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin }; static const uint16_t end_cmd[2] = { 4, X_GLrop_End }; single_vertex_size = calculate_single_vertex_size_none( arrays ); pc = gc->pc; (void) memcpy( pc, begin_cmd, 4 ); *(int *)(pc + 4) = mode; pc += 8; for ( i = 0 ; i < count ; i++ ) { if ( (pc + single_vertex_size) >= gc->bufEnd ) { pc = __glXFlushRenderBuffer(gc, pc); } pc = emit_element_none( pc, arrays, first + i ); } if ( (pc + 4) >= gc->bufEnd ) { pc = __glXFlushRenderBuffer(gc, pc); } (void) memcpy( pc, end_cmd, 4 ); pc += 4; gc->pc = pc; if ( gc->pc > gc->limit ) { (void) __glXFlushRenderBuffer(gc, gc->pc); }}/** * Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays * protocol. * * \param gc GLX context. * \param arrays Array state. * \param elements_per_request Location to store the number of elements that * can fit in a single Render / RenderLarge * command. * \param total_request Total number of requests for a RenderLarge * command. If a Render command is used, this * will be zero. * \param mode Drawing mode. * \param count Number of vertices. * * \returns * A pointer to the buffer for array data. */static GLubyte *emit_DrawArrays_header_old( __GLXcontext * gc, struct array_state_vector * arrays, size_t * elements_per_request, unsigned int * total_requests, GLenum mode, GLsizei count ){ size_t command_size; size_t single_vertex_size; const unsigned header_size = 16; unsigned i; GLubyte * pc; /* Determine the size of the whole command. This includes the header, * the ARRAY_INFO data and the array data. Once this size is calculated, * it will be known whether a Render or RenderLarge command is needed. */ single_vertex_size = 0; for ( i = 0 ; i < arrays->num_arrays ; i++ ) { if ( arrays->arrays[i].enabled ) { single_vertex_size += __GLX_PAD( arrays->arrays[i].element_size ); } } command_size = arrays->array_info_cache_size + header_size + (single_vertex_size * count); /* Write the header for either a Render command or a RenderLarge * command. After the header is written, write the ARRAY_INFO data. */ if ( command_size > gc->maxSmallRenderCommandSize ) { /* maxSize is the maximum amount of data can be stuffed into a single * packet. sz_xGLXRenderReq is added because bufSize is the maximum * packet size minus sz_xGLXRenderReq. */ const size_t maxSize = (gc->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; unsigned vertex_requests; /* Calculate the number of data packets that will be required to send * the whole command. To do this, the number of verticies that * will fit in a single buffer must be calculated. * * The important value here is elements_per_request. This is the * number of complete array elements that will fit in a single * buffer. There may be some wasted space at the end of the buffer, * but splitting elements across buffer boundries would be painful. */ elements_per_request[0] = maxSize / single_vertex_size; vertex_requests = (count + elements_per_request[0] - 1) / elements_per_request[0]; *total_requests = vertex_requests + 1; __glXFlushRenderBuffer(gc, gc->pc); command_size += 4; pc = ((GLubyte *) arrays->array_info_cache) - (header_size + 4); *(uint32_t *)(pc + 0) = command_size; *(uint32_t *)(pc + 4) = X_GLrop_DrawArrays; *(uint32_t *)(pc + 8) = count; *(uint32_t *)(pc + 12) = arrays->enabled_client_array_count; *(uint32_t *)(pc + 16) = mode; __glXSendLargeChunk( gc, 1, *total_requests, pc, header_size + 4 + arrays->array_info_cache_size ); pc = gc->pc; } else { if ( (gc->pc + command_size) >= gc->bufEnd ) { (void) __glXFlushRenderBuffer(gc, gc->pc); } pc = gc->pc; *(uint16_t *)(pc + 0) = command_size; *(uint16_t *)(pc + 2) = X_GLrop_DrawArrays; *(uint32_t *)(pc + 4) = count; *(uint32_t *)(pc + 8) = arrays->enabled_client_array_count; *(uint32_t *)(pc + 12) = mode; pc += header_size; (void) memcpy( pc, arrays->array_info_cache, arrays->array_info_cache_size ); pc += arrays->array_info_cache_size; *elements_per_request = count; *total_requests = 0; } return pc;}/** */voidemit_DrawArrays_old( GLenum mode, GLint first, GLsizei count ){ __GLXcontext *gc = __glXGetCurrentContext(); const __GLXattribute * state = (const __GLXattribute *)(gc->client_state_private); struct array_state_vector * arrays = state->array_state; GLubyte * pc; size_t elements_per_request; unsigned total_requests = 0; unsigned i; size_t total_sent = 0; pc = emit_DrawArrays_header_old( gc, arrays, & elements_per_request, & total_requests, mode, count); /* Write the arrays. */ if ( total_requests == 0 ) { assert( elements_per_request >= count ); for ( i = 0 ; i < count ; i++ ) { pc = emit_element_old( pc, arrays, i + first ); } assert( pc <= gc->bufEnd ); gc->pc = pc; if ( gc->pc > gc->limit ) { (void) __glXFlushRenderBuffer(gc, gc->pc); } } else { unsigned req; for ( req = 2 ; req <= total_requests ; req++ ) { if ( count < elements_per_request ) { elements_per_request = count; } pc = gc->pc; for ( i = 0 ; i < elements_per_request ; i++ ) { pc = emit_element_old( pc, arrays, i + first ); } first += elements_per_request; total_sent += (size_t) (pc - gc->pc); __glXSendLargeChunk( gc, req, total_requests, gc->pc, pc - gc->pc ); count -= elements_per_request; } }}voidemit_DrawElements_none( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ){ __GLXcontext *gc = __glXGetCurrentContext(); const __GLXattribute * state = (const __GLXattribute *)(gc->client_state_private); struct array_state_vector * arrays = state->array_state; static const uint16_t begin_cmd[2] = { 8, X_GLrop_Begin }; static const uint16_t end_cmd[2] = { 4, X_GLrop_End }; GLubyte * pc; size_t single_vertex_size; unsigned i; single_vertex_size = calculate_single_vertex_size_none( arrays ); if ( (gc->pc + single_vertex_size) >= gc->bufEnd ) { gc->pc = __glXFlushRenderBuffer(gc, gc->pc); } pc = gc->pc; (void) memcpy( pc, begin_cmd, 4 ); *(int *)(pc + 4) = mode; pc += 8; for ( i = 0 ; i < count ; i++ ) { unsigned index = 0; if ( (pc + single_vertex_size) >= gc->bufEnd ) { pc = __glXFlushRenderBuffer(gc, pc); } switch( type ) { case GL_UNSIGNED_INT: index = (unsigned) (((GLuint *) indices)[i]); break; case GL_UNSIGNED_SHORT: index = (unsigned) (((GLushort *) indices)[i]); break; case GL_UNSIGNED_BYTE: index = (unsigned) (((GLubyte *) indices)[i]); break; } pc = emit_element_none( pc, arrays, index ); } if ( (pc + 4) >= gc->bufEnd ) { pc = __glXFlushRenderBuffer(gc, pc); } (void) memcpy( pc, end_cmd, 4 ); pc += 4; gc->pc = pc; if ( gc->pc > gc->limit ) { (void) __glXFlushRenderBuffer(gc, gc->pc); }}/** */voidemit_DrawElements_old( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ){ __GLXcontext *gc = __glXGetCurrentContext(); const __GLXattribute * state = (const __GLXattribute *)(gc->client_state_private); struct array_state_vector * arrays = state->array_state; GLubyte * pc; size_t elements_per_request; unsigned total_requests = 0; unsigned i; unsigned req; unsigned req_element=0; pc = emit_DrawArrays_header_old( gc, arrays, & elements_per_request, & total_requests, mode, count); /* Write the arrays. */ req = 2; while ( count > 0 ) { if ( count < elements_per_request ) { elements_per_request = count; } switch( type ) { case GL_UNSIGNED_INT: { const GLuint * ui_ptr = (const GLuint *) indices + req_element; for ( i = 0 ; i < elements_per_request ; i++ ) { const GLint index = (GLint) *(ui_ptr++); pc = emit_element_old( pc, arrays, index ); } break; } case GL_UNSIGNED_SHORT: { const GLushort * us_ptr = (const GLushort *) indices + req_element; for ( i = 0 ; i < elements_per_request ; i++ ) { const GLint index = (GLint) *(us_ptr++); pc = emit_element_old( pc, arrays, index ); } break; } case GL_UNSIGNED_BYTE: { const GLubyte * ub_ptr = (const GLubyte *) indices + req_element; for ( i = 0 ; i < elements_per_request ; i++ ) { const GLint index = (GLint) *(ub_ptr++); pc = emit_element_old( pc, arrays, index ); } break; } } if ( total_requests != 0 ) { __glXSendLargeChunk( gc, req, total_requests, gc->pc, pc - gc->pc ); pc = gc->pc; req++; } count -= elements_per_request; req_element += elements_per_request; } assert( (total_requests == 0) || ((req - 1) == total_requests) ); if ( total_requests == 0 ) { assert( pc <= gc->bufEnd ); gc->pc = pc; if ( gc->pc > gc->limit ) { (void) __glXFlushRenderBuffer(gc, gc->pc); } }}/** * Validate that the \c mode parameter to \c glDrawArrays, et. al. is valid. * If it is not valid, then an error code is set in the GLX context. * * \returns * \c GL_TRUE if the argument is valid, \c GL_FALSE if is not. */static GLbooleanvalidate_mode(__GLXcontext *gc, GLenum mode){ switch(mode) { case GL_POINTS: case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_LINES: case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_TRIANGLES: case GL_QUAD_STRIP: case GL_QUADS: case GL_POLYGON: break; default: __glXSetError(gc, GL_INVALID_ENUM); return GL_FALSE; } return GL_TRUE;}/** * Validate that the \c count parameter to \c glDrawArrays, et. al. is valid. * A value less than zero is invalid and will result in \c GL_INVALID_VALUE * being set. A value of zero will not result in an error being set, but * will result in \c GL_FALSE being returned. * * \returns * \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not. */static GLbooleanvalidate_count(__GLXcontext *gc, GLsizei count){ if (count < 0) { __glXSetError(gc, GL_INVALID_VALUE); } return (count > 0);}/** * Validate that the \c type parameter to \c glDrawElements, et. al. is * valid. Only \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, and * \c GL_UNSIGNED_INT are valid. * * \returns * \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not. */static GLboolean validate_type(__GLXcontext *gc, GLenum type){ switch( type ) { case GL_UNSIGNED_INT: case GL_UNSIGNED_SHORT: case GL_UNSIGNED_BYTE: return GL_TRUE; default: __glXSetError(gc, GL_INVALID_ENUM); return GL_FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -