1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2003 VMware, Inc. 4bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc. 5bf215546Sopenharmony_ci * All Rights Reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 13bf215546Sopenharmony_ci * the following conditions: 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 17bf215546Sopenharmony_ci * of the Software. 18bf215546Sopenharmony_ci * 19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26bf215546Sopenharmony_ci * 27bf215546Sopenharmony_ci **************************************************************************/ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include <stdio.h> 30bf215546Sopenharmony_ci#include "arrayobj.h" 31bf215546Sopenharmony_ci#include "glheader.h" 32bf215546Sopenharmony_ci#include "c99_alloca.h" 33bf215546Sopenharmony_ci#include "context.h" 34bf215546Sopenharmony_ci#include "state.h" 35bf215546Sopenharmony_ci#include "draw.h" 36bf215546Sopenharmony_ci#include "draw_validate.h" 37bf215546Sopenharmony_ci#include "dispatch.h" 38bf215546Sopenharmony_ci#include "varray.h" 39bf215546Sopenharmony_ci#include "bufferobj.h" 40bf215546Sopenharmony_ci#include "enums.h" 41bf215546Sopenharmony_ci#include "macros.h" 42bf215546Sopenharmony_ci#include "transformfeedback.h" 43bf215546Sopenharmony_ci#include "pipe/p_state.h" 44bf215546Sopenharmony_ci#include "api_exec_decl.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#include "state_tracker/st_context.h" 47bf215546Sopenharmony_ci#include "state_tracker/st_draw.h" 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_citypedef struct { 50bf215546Sopenharmony_ci GLuint count; 51bf215546Sopenharmony_ci GLuint primCount; 52bf215546Sopenharmony_ci GLuint first; 53bf215546Sopenharmony_ci GLuint baseInstance; 54bf215546Sopenharmony_ci} DrawArraysIndirectCommand; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_citypedef struct { 57bf215546Sopenharmony_ci GLuint count; 58bf215546Sopenharmony_ci GLuint primCount; 59bf215546Sopenharmony_ci GLuint firstIndex; 60bf215546Sopenharmony_ci GLint baseVertex; 61bf215546Sopenharmony_ci GLuint baseInstance; 62bf215546Sopenharmony_ci} DrawElementsIndirectCommand; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci/** 66bf215546Sopenharmony_ci * Want to figure out which fragment program inputs are actually 67bf215546Sopenharmony_ci * constant/current values from ctx->Current. These should be 68bf215546Sopenharmony_ci * referenced as a tracked state variable rather than a fragment 69bf215546Sopenharmony_ci * program input, to save the overhead of putting a constant value in 70bf215546Sopenharmony_ci * every submitted vertex, transferring it to hardware, interpolating 71bf215546Sopenharmony_ci * it across the triangle, etc... 72bf215546Sopenharmony_ci * 73bf215546Sopenharmony_ci * When there is a VP bound, just use vp->outputs. But when we're 74bf215546Sopenharmony_ci * generating vp from fixed function state, basically want to 75bf215546Sopenharmony_ci * calculate: 76bf215546Sopenharmony_ci * 77bf215546Sopenharmony_ci * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) | 78bf215546Sopenharmony_ci * potential_vp_outputs ) 79bf215546Sopenharmony_ci * 80bf215546Sopenharmony_ci * Where potential_vp_outputs is calculated by looking at enabled 81bf215546Sopenharmony_ci * texgen, etc. 82bf215546Sopenharmony_ci * 83bf215546Sopenharmony_ci * The generated fragment program should then only declare inputs that 84bf215546Sopenharmony_ci * may vary or otherwise differ from the ctx->Current values. 85bf215546Sopenharmony_ci * Otherwise, the fp should track them as state values instead. 86bf215546Sopenharmony_ci */ 87bf215546Sopenharmony_civoid 88bf215546Sopenharmony_ci_mesa_set_varying_vp_inputs(struct gl_context *ctx, GLbitfield varying_inputs) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci if (ctx->VertexProgram._VPModeOptimizesConstantAttribs && 91bf215546Sopenharmony_ci ctx->VertexProgram._VaryingInputs != varying_inputs) { 92bf215546Sopenharmony_ci ctx->VertexProgram._VaryingInputs = varying_inputs; 93bf215546Sopenharmony_ci ctx->NewState |= _NEW_FF_VERT_PROGRAM | _NEW_FF_FRAG_PROGRAM; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci/** 99bf215546Sopenharmony_ci * Set the _DrawVAO and the net enabled arrays. 100bf215546Sopenharmony_ci * The vao->_Enabled bitmask is transformed due to position/generic0 101bf215546Sopenharmony_ci * as stored in vao->_AttributeMapMode. Then the filter bitmask is applied 102bf215546Sopenharmony_ci * to filter out arrays unwanted for the currently executed draw operation. 103bf215546Sopenharmony_ci * For example, the generic attributes are masked out form the _DrawVAO's 104bf215546Sopenharmony_ci * enabled arrays when a fixed function array draw is executed. 105bf215546Sopenharmony_ci */ 106bf215546Sopenharmony_civoid 107bf215546Sopenharmony_ci_mesa_set_draw_vao(struct gl_context *ctx, struct gl_vertex_array_object *vao, 108bf215546Sopenharmony_ci GLbitfield filter) 109bf215546Sopenharmony_ci{ 110bf215546Sopenharmony_ci struct gl_vertex_array_object **ptr = &ctx->Array._DrawVAO; 111bf215546Sopenharmony_ci bool new_vertex_buffers = false, new_vertex_elements = false; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (*ptr != vao) { 114bf215546Sopenharmony_ci _mesa_reference_vao_(ctx, ptr, vao); 115bf215546Sopenharmony_ci new_vertex_buffers = true; 116bf215546Sopenharmony_ci new_vertex_elements = true; 117bf215546Sopenharmony_ci } 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci if (vao->NewVertexBuffers || vao->NewVertexElements) { 120bf215546Sopenharmony_ci _mesa_update_vao_derived_arrays(ctx, vao); 121bf215546Sopenharmony_ci new_vertex_buffers |= vao->NewVertexBuffers; 122bf215546Sopenharmony_ci new_vertex_elements |= vao->NewVertexElements; 123bf215546Sopenharmony_ci vao->NewVertexBuffers = false; 124bf215546Sopenharmony_ci vao->NewVertexElements = false; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci assert(vao->_EnabledWithMapMode == 128bf215546Sopenharmony_ci _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled)); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci /* Filter out unwanted arrays. */ 131bf215546Sopenharmony_ci const GLbitfield enabled = filter & vao->_EnabledWithMapMode; 132bf215546Sopenharmony_ci if (ctx->Array._DrawVAOEnabledAttribs != enabled) { 133bf215546Sopenharmony_ci ctx->Array._DrawVAOEnabledAttribs = enabled; 134bf215546Sopenharmony_ci new_vertex_buffers = true; 135bf215546Sopenharmony_ci new_vertex_elements = true; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci if (new_vertex_buffers || new_vertex_elements) { 139bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS; 140bf215546Sopenharmony_ci ctx->Array.NewVertexElements |= new_vertex_elements; 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci _mesa_set_varying_vp_inputs(ctx, enabled); 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci/** 148bf215546Sopenharmony_ci * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(), 149bf215546Sopenharmony_ci * etc? Also, do additional checking related to transformation feedback. 150bf215546Sopenharmony_ci * Note: this function cannot be called during glNewList(GL_COMPILE) because 151bf215546Sopenharmony_ci * this code depends on current transform feedback state. 152bf215546Sopenharmony_ci * Also, do additional checking related to tessellation shaders. 153bf215546Sopenharmony_ci */ 154bf215546Sopenharmony_cistatic GLenum 155bf215546Sopenharmony_civalid_prim_mode_custom(struct gl_context *ctx, GLenum mode, 156bf215546Sopenharmony_ci GLbitfield valid_prim_mask) 157bf215546Sopenharmony_ci{ 158bf215546Sopenharmony_ci#if DEBUG 159bf215546Sopenharmony_ci unsigned mask = ctx->ValidPrimMask; 160bf215546Sopenharmony_ci unsigned mask_indexed = ctx->ValidPrimMaskIndexed; 161bf215546Sopenharmony_ci bool drawpix_valid = ctx->DrawPixValid; 162bf215546Sopenharmony_ci _mesa_update_valid_to_render_state(ctx); 163bf215546Sopenharmony_ci assert(mask == ctx->ValidPrimMask && 164bf215546Sopenharmony_ci mask_indexed == ctx->ValidPrimMaskIndexed && 165bf215546Sopenharmony_ci drawpix_valid == ctx->DrawPixValid); 166bf215546Sopenharmony_ci#endif 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci /* All primitive type enums are less than 32, so we can use the shift. */ 169bf215546Sopenharmony_ci if (mode >= 32 || !((1u << mode) & valid_prim_mask)) { 170bf215546Sopenharmony_ci /* If the primitive type is not in SupportedPrimMask, set GL_INVALID_ENUM, 171bf215546Sopenharmony_ci * else set DrawGLError (e.g. GL_INVALID_OPERATION). 172bf215546Sopenharmony_ci */ 173bf215546Sopenharmony_ci return mode >= 32 || !((1u << mode) & ctx->SupportedPrimMask) ? 174bf215546Sopenharmony_ci GL_INVALID_ENUM : ctx->DrawGLError; 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci return GL_NO_ERROR; 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ciGLenum 181bf215546Sopenharmony_ci_mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode) 182bf215546Sopenharmony_ci{ 183bf215546Sopenharmony_ci return valid_prim_mode_custom(ctx, mode, ctx->ValidPrimMask); 184bf215546Sopenharmony_ci} 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_cistatic GLenum 187bf215546Sopenharmony_civalid_prim_mode_indexed(struct gl_context *ctx, GLenum mode) 188bf215546Sopenharmony_ci{ 189bf215546Sopenharmony_ci return valid_prim_mode_custom(ctx, mode, ctx->ValidPrimMaskIndexed); 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci/** 193bf215546Sopenharmony_ci * Verify that the element type is valid. 194bf215546Sopenharmony_ci * 195bf215546Sopenharmony_ci * Generates \c GL_INVALID_ENUM and returns \c false if it is not. 196bf215546Sopenharmony_ci */ 197bf215546Sopenharmony_cistatic GLenum 198bf215546Sopenharmony_civalid_elements_type(struct gl_context *ctx, GLenum type) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci /* GL_UNSIGNED_BYTE = 0x1401 201bf215546Sopenharmony_ci * GL_UNSIGNED_SHORT = 0x1403 202bf215546Sopenharmony_ci * GL_UNSIGNED_INT = 0x1405 203bf215546Sopenharmony_ci * 204bf215546Sopenharmony_ci * The trick is that bit 1 and bit 2 mean USHORT and UINT, respectively. 205bf215546Sopenharmony_ci * After clearing those two bits (with ~6), we should get UBYTE. 206bf215546Sopenharmony_ci * Both bits can't be set, because the enum would be greater than UINT. 207bf215546Sopenharmony_ci */ 208bf215546Sopenharmony_ci if (!(type <= GL_UNSIGNED_INT && (type & ~6) == GL_UNSIGNED_BYTE)) 209bf215546Sopenharmony_ci return GL_INVALID_ENUM; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci return GL_NO_ERROR; 212bf215546Sopenharmony_ci} 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_cistatic inline bool 215bf215546Sopenharmony_ciindices_aligned(unsigned index_size_shift, const GLvoid *indices) 216bf215546Sopenharmony_ci{ 217bf215546Sopenharmony_ci /* Require that indices are aligned to the element size. GL doesn't specify 218bf215546Sopenharmony_ci * an error for this, but the ES 3.0 spec says: 219bf215546Sopenharmony_ci * 220bf215546Sopenharmony_ci * "Clients must align data elements consistently with the requirements 221bf215546Sopenharmony_ci * of the client platform, with an additional base-level requirement 222bf215546Sopenharmony_ci * that an offset within a buffer to a datum comprising N basic machine 223bf215546Sopenharmony_ci * units be a multiple of N" 224bf215546Sopenharmony_ci * 225bf215546Sopenharmony_ci * This is only required by index buffers, not user indices. 226bf215546Sopenharmony_ci */ 227bf215546Sopenharmony_ci return ((uintptr_t)indices & ((1 << index_size_shift) - 1)) == 0; 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_cistatic GLenum 231bf215546Sopenharmony_civalidate_DrawElements_common(struct gl_context *ctx, GLenum mode, 232bf215546Sopenharmony_ci GLsizei count, GLsizei numInstances, GLenum type) 233bf215546Sopenharmony_ci{ 234bf215546Sopenharmony_ci if (count < 0 || numInstances < 0) 235bf215546Sopenharmony_ci return GL_INVALID_VALUE; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci GLenum error = valid_prim_mode_indexed(ctx, mode); 238bf215546Sopenharmony_ci if (error) 239bf215546Sopenharmony_ci return error; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci return valid_elements_type(ctx, type); 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci/** 245bf215546Sopenharmony_ci * Error checking for glDrawElements(). Includes parameter checking 246bf215546Sopenharmony_ci * and VBO bounds checking. 247bf215546Sopenharmony_ci * \return GL_TRUE if OK to render, GL_FALSE if error found 248bf215546Sopenharmony_ci */ 249bf215546Sopenharmony_cistatic GLboolean 250bf215546Sopenharmony_ci_mesa_validate_DrawElements(struct gl_context *ctx, 251bf215546Sopenharmony_ci GLenum mode, GLsizei count, GLenum type) 252bf215546Sopenharmony_ci{ 253bf215546Sopenharmony_ci GLenum error = validate_DrawElements_common(ctx, mode, count, 1, type); 254bf215546Sopenharmony_ci if (error) 255bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawElements"); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci return !error; 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci/** 262bf215546Sopenharmony_ci * Error checking for glMultiDrawElements(). Includes parameter checking 263bf215546Sopenharmony_ci * and VBO bounds checking. 264bf215546Sopenharmony_ci * \return GL_TRUE if OK to render, GL_FALSE if error found 265bf215546Sopenharmony_ci */ 266bf215546Sopenharmony_cistatic GLboolean 267bf215546Sopenharmony_ci_mesa_validate_MultiDrawElements(struct gl_context *ctx, 268bf215546Sopenharmony_ci GLenum mode, const GLsizei *count, 269bf215546Sopenharmony_ci GLenum type, const GLvoid * const *indices, 270bf215546Sopenharmony_ci GLsizei primcount) 271bf215546Sopenharmony_ci{ 272bf215546Sopenharmony_ci GLenum error; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci /* 275bf215546Sopenharmony_ci * Section 2.3.1 (Errors) of the OpenGL 4.5 (Core Profile) spec says: 276bf215546Sopenharmony_ci * 277bf215546Sopenharmony_ci * "If a negative number is provided where an argument of type sizei or 278bf215546Sopenharmony_ci * sizeiptr is specified, an INVALID_VALUE error is generated." 279bf215546Sopenharmony_ci * 280bf215546Sopenharmony_ci * and in the same section: 281bf215546Sopenharmony_ci * 282bf215546Sopenharmony_ci * "In other cases, there are no side effects unless otherwise noted; 283bf215546Sopenharmony_ci * the command which generates the error is ignored so that it has no 284bf215546Sopenharmony_ci * effect on GL state or framebuffer contents." 285bf215546Sopenharmony_ci * 286bf215546Sopenharmony_ci * Hence, check both primcount and all the count[i]. 287bf215546Sopenharmony_ci */ 288bf215546Sopenharmony_ci if (primcount < 0) { 289bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 290bf215546Sopenharmony_ci } else { 291bf215546Sopenharmony_ci error = valid_prim_mode_indexed(ctx, mode); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci if (!error) { 294bf215546Sopenharmony_ci error = valid_elements_type(ctx, type); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci if (!error) { 297bf215546Sopenharmony_ci for (int i = 0; i < primcount; i++) { 298bf215546Sopenharmony_ci if (count[i] < 0) { 299bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 300bf215546Sopenharmony_ci break; 301bf215546Sopenharmony_ci } 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci if (error) 308bf215546Sopenharmony_ci _mesa_error(ctx, error, "glMultiDrawElements"); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci /* Not using a VBO for indices, so avoid NULL pointer derefs later. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_ci if (!ctx->Array.VAO->IndexBufferObj) { 313bf215546Sopenharmony_ci for (int i = 0; i < primcount; i++) { 314bf215546Sopenharmony_ci if (!indices[i]) 315bf215546Sopenharmony_ci return GL_FALSE; 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci return !error; 320bf215546Sopenharmony_ci} 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci/** 324bf215546Sopenharmony_ci * Error checking for glDrawRangeElements(). Includes parameter checking 325bf215546Sopenharmony_ci * and VBO bounds checking. 326bf215546Sopenharmony_ci * \return GL_TRUE if OK to render, GL_FALSE if error found 327bf215546Sopenharmony_ci */ 328bf215546Sopenharmony_cistatic GLboolean 329bf215546Sopenharmony_ci_mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode, 330bf215546Sopenharmony_ci GLuint start, GLuint end, 331bf215546Sopenharmony_ci GLsizei count, GLenum type) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci GLenum error; 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci if (end < start) { 336bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 337bf215546Sopenharmony_ci } else { 338bf215546Sopenharmony_ci error = validate_DrawElements_common(ctx, mode, count, 1, type); 339bf215546Sopenharmony_ci } 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci if (error) 342bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawRangeElements"); 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci return !error; 345bf215546Sopenharmony_ci} 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_cistatic bool 349bf215546Sopenharmony_cineed_xfb_remaining_prims_check(const struct gl_context *ctx) 350bf215546Sopenharmony_ci{ 351bf215546Sopenharmony_ci /* From the GLES3 specification, section 2.14.2 (Transform Feedback 352bf215546Sopenharmony_ci * Primitive Capture): 353bf215546Sopenharmony_ci * 354bf215546Sopenharmony_ci * The error INVALID_OPERATION is generated by DrawArrays and 355bf215546Sopenharmony_ci * DrawArraysInstanced if recording the vertices of a primitive to the 356bf215546Sopenharmony_ci * buffer objects being used for transform feedback purposes would result 357bf215546Sopenharmony_ci * in either exceeding the limits of any buffer object’s size, or in 358bf215546Sopenharmony_ci * exceeding the end position offset + size − 1, as set by 359bf215546Sopenharmony_ci * BindBufferRange. 360bf215546Sopenharmony_ci * 361bf215546Sopenharmony_ci * This is in contrast to the behaviour of desktop GL, where the extra 362bf215546Sopenharmony_ci * primitives are silently dropped from the transform feedback buffer. 363bf215546Sopenharmony_ci * 364bf215546Sopenharmony_ci * This text is removed in ES 3.2, presumably because it's not really 365bf215546Sopenharmony_ci * implementable with geometry and tessellation shaders. In fact, 366bf215546Sopenharmony_ci * the OES_geometry_shader spec says: 367bf215546Sopenharmony_ci * 368bf215546Sopenharmony_ci * "(13) Does this extension change how transform feedback operates 369bf215546Sopenharmony_ci * compared to unextended OpenGL ES 3.0 or 3.1? 370bf215546Sopenharmony_ci * 371bf215546Sopenharmony_ci * RESOLVED: Yes. Because dynamic geometry amplification in a geometry 372bf215546Sopenharmony_ci * shader can make it difficult if not impossible to predict the amount 373bf215546Sopenharmony_ci * of geometry that may be generated in advance of executing the shader, 374bf215546Sopenharmony_ci * the draw-time error for transform feedback buffer overflow conditions 375bf215546Sopenharmony_ci * is removed and replaced with the GL behavior (primitives are not 376bf215546Sopenharmony_ci * written and the corresponding counter is not updated)..." 377bf215546Sopenharmony_ci */ 378bf215546Sopenharmony_ci return _mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx) && 379bf215546Sopenharmony_ci !_mesa_has_OES_geometry_shader(ctx) && 380bf215546Sopenharmony_ci !_mesa_has_OES_tessellation_shader(ctx); 381bf215546Sopenharmony_ci} 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci/** 385bf215546Sopenharmony_ci * Figure out the number of transform feedback primitives that will be output 386bf215546Sopenharmony_ci * considering the drawing mode, number of vertices, and instance count, 387bf215546Sopenharmony_ci * assuming that no geometry shading is done and primitive restart is not 388bf215546Sopenharmony_ci * used. 389bf215546Sopenharmony_ci * 390bf215546Sopenharmony_ci * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED 391bf215546Sopenharmony_ci * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. It is also used to 392bf215546Sopenharmony_ci * pre-validate draw calls in GLES3 (where draw calls only succeed if there is 393bf215546Sopenharmony_ci * enough room in the transform feedback buffer for the result). 394bf215546Sopenharmony_ci */ 395bf215546Sopenharmony_cistatic size_t 396bf215546Sopenharmony_cicount_tessellated_primitives(GLenum mode, GLuint count, GLuint num_instances) 397bf215546Sopenharmony_ci{ 398bf215546Sopenharmony_ci size_t num_primitives; 399bf215546Sopenharmony_ci switch (mode) { 400bf215546Sopenharmony_ci case GL_POINTS: 401bf215546Sopenharmony_ci num_primitives = count; 402bf215546Sopenharmony_ci break; 403bf215546Sopenharmony_ci case GL_LINE_STRIP: 404bf215546Sopenharmony_ci num_primitives = count >= 2 ? count - 1 : 0; 405bf215546Sopenharmony_ci break; 406bf215546Sopenharmony_ci case GL_LINE_LOOP: 407bf215546Sopenharmony_ci num_primitives = count >= 2 ? count : 0; 408bf215546Sopenharmony_ci break; 409bf215546Sopenharmony_ci case GL_LINES: 410bf215546Sopenharmony_ci num_primitives = count / 2; 411bf215546Sopenharmony_ci break; 412bf215546Sopenharmony_ci case GL_TRIANGLE_STRIP: 413bf215546Sopenharmony_ci case GL_TRIANGLE_FAN: 414bf215546Sopenharmony_ci case GL_POLYGON: 415bf215546Sopenharmony_ci num_primitives = count >= 3 ? count - 2 : 0; 416bf215546Sopenharmony_ci break; 417bf215546Sopenharmony_ci case GL_TRIANGLES: 418bf215546Sopenharmony_ci num_primitives = count / 3; 419bf215546Sopenharmony_ci break; 420bf215546Sopenharmony_ci case GL_QUAD_STRIP: 421bf215546Sopenharmony_ci num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0; 422bf215546Sopenharmony_ci break; 423bf215546Sopenharmony_ci case GL_QUADS: 424bf215546Sopenharmony_ci num_primitives = (count / 4) * 2; 425bf215546Sopenharmony_ci break; 426bf215546Sopenharmony_ci case GL_LINES_ADJACENCY: 427bf215546Sopenharmony_ci num_primitives = count / 4; 428bf215546Sopenharmony_ci break; 429bf215546Sopenharmony_ci case GL_LINE_STRIP_ADJACENCY: 430bf215546Sopenharmony_ci num_primitives = count >= 4 ? count - 3 : 0; 431bf215546Sopenharmony_ci break; 432bf215546Sopenharmony_ci case GL_TRIANGLES_ADJACENCY: 433bf215546Sopenharmony_ci num_primitives = count / 6; 434bf215546Sopenharmony_ci break; 435bf215546Sopenharmony_ci case GL_TRIANGLE_STRIP_ADJACENCY: 436bf215546Sopenharmony_ci num_primitives = count >= 6 ? (count - 4) / 2 : 0; 437bf215546Sopenharmony_ci break; 438bf215546Sopenharmony_ci default: 439bf215546Sopenharmony_ci assert(!"Unexpected primitive type in count_tessellated_primitives"); 440bf215546Sopenharmony_ci num_primitives = 0; 441bf215546Sopenharmony_ci break; 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci return num_primitives * num_instances; 444bf215546Sopenharmony_ci} 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_cistatic GLenum 448bf215546Sopenharmony_civalidate_draw_arrays(struct gl_context *ctx, 449bf215546Sopenharmony_ci GLenum mode, GLsizei count, GLsizei numInstances) 450bf215546Sopenharmony_ci{ 451bf215546Sopenharmony_ci if (count < 0 || numInstances < 0) 452bf215546Sopenharmony_ci return GL_INVALID_VALUE; 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci GLenum error = _mesa_valid_prim_mode(ctx, mode); 455bf215546Sopenharmony_ci if (error) 456bf215546Sopenharmony_ci return error; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci if (need_xfb_remaining_prims_check(ctx)) { 459bf215546Sopenharmony_ci struct gl_transform_feedback_object *xfb_obj 460bf215546Sopenharmony_ci = ctx->TransformFeedback.CurrentObject; 461bf215546Sopenharmony_ci size_t prim_count = count_tessellated_primitives(mode, count, numInstances); 462bf215546Sopenharmony_ci if (xfb_obj->GlesRemainingPrims < prim_count) 463bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci xfb_obj->GlesRemainingPrims -= prim_count; 466bf215546Sopenharmony_ci } 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci return GL_NO_ERROR; 469bf215546Sopenharmony_ci} 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci/** 472bf215546Sopenharmony_ci * Called from the tnl module to error check the function parameters and 473bf215546Sopenharmony_ci * verify that we really can draw something. 474bf215546Sopenharmony_ci * \return GL_TRUE if OK to render, GL_FALSE if error found 475bf215546Sopenharmony_ci */ 476bf215546Sopenharmony_cistatic GLboolean 477bf215546Sopenharmony_ci_mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count) 478bf215546Sopenharmony_ci{ 479bf215546Sopenharmony_ci GLenum error = validate_draw_arrays(ctx, mode, count, 1); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci if (error) 482bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawArrays"); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci return !error; 485bf215546Sopenharmony_ci} 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_cistatic GLboolean 489bf215546Sopenharmony_ci_mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first, 490bf215546Sopenharmony_ci GLsizei count, GLsizei numInstances) 491bf215546Sopenharmony_ci{ 492bf215546Sopenharmony_ci GLenum error; 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci if (first < 0) { 495bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 496bf215546Sopenharmony_ci } else { 497bf215546Sopenharmony_ci error = validate_draw_arrays(ctx, mode, count, numInstances); 498bf215546Sopenharmony_ci } 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci if (error) 501bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawArraysInstanced"); 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci return !error; 504bf215546Sopenharmony_ci} 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci/** 508bf215546Sopenharmony_ci * Called to error check the function parameters. 509bf215546Sopenharmony_ci * 510bf215546Sopenharmony_ci * Note that glMultiDrawArrays is not part of GLES, so there's limited scope 511bf215546Sopenharmony_ci * for sharing code with the validation of glDrawArrays. 512bf215546Sopenharmony_ci */ 513bf215546Sopenharmony_cistatic bool 514bf215546Sopenharmony_ci_mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode, 515bf215546Sopenharmony_ci const GLsizei *count, GLsizei primcount) 516bf215546Sopenharmony_ci{ 517bf215546Sopenharmony_ci GLenum error; 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci if (primcount < 0) { 520bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 521bf215546Sopenharmony_ci } else { 522bf215546Sopenharmony_ci error = _mesa_valid_prim_mode(ctx, mode); 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci if (!error) { 525bf215546Sopenharmony_ci for (int i = 0; i < primcount; ++i) { 526bf215546Sopenharmony_ci if (count[i] < 0) { 527bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 528bf215546Sopenharmony_ci break; 529bf215546Sopenharmony_ci } 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci if (!error) { 533bf215546Sopenharmony_ci if (need_xfb_remaining_prims_check(ctx)) { 534bf215546Sopenharmony_ci struct gl_transform_feedback_object *xfb_obj 535bf215546Sopenharmony_ci = ctx->TransformFeedback.CurrentObject; 536bf215546Sopenharmony_ci size_t xfb_prim_count = 0; 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci for (int i = 0; i < primcount; ++i) { 539bf215546Sopenharmony_ci xfb_prim_count += 540bf215546Sopenharmony_ci count_tessellated_primitives(mode, count[i], 1); 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (xfb_obj->GlesRemainingPrims < xfb_prim_count) { 544bf215546Sopenharmony_ci error = GL_INVALID_OPERATION; 545bf215546Sopenharmony_ci } else { 546bf215546Sopenharmony_ci xfb_obj->GlesRemainingPrims -= xfb_prim_count; 547bf215546Sopenharmony_ci } 548bf215546Sopenharmony_ci } 549bf215546Sopenharmony_ci } 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci } 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci if (error) 554bf215546Sopenharmony_ci _mesa_error(ctx, error, "glMultiDrawArrays"); 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci return !error; 557bf215546Sopenharmony_ci} 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_cistatic GLboolean 561bf215546Sopenharmony_ci_mesa_validate_DrawElementsInstanced(struct gl_context *ctx, 562bf215546Sopenharmony_ci GLenum mode, GLsizei count, GLenum type, 563bf215546Sopenharmony_ci GLsizei numInstances) 564bf215546Sopenharmony_ci{ 565bf215546Sopenharmony_ci GLenum error = 566bf215546Sopenharmony_ci validate_DrawElements_common(ctx, mode, count, numInstances, type); 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci if (error) 569bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawElementsInstanced"); 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci return !error; 572bf215546Sopenharmony_ci} 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_cistatic GLboolean 576bf215546Sopenharmony_ci_mesa_validate_DrawTransformFeedback(struct gl_context *ctx, 577bf215546Sopenharmony_ci GLenum mode, 578bf215546Sopenharmony_ci struct gl_transform_feedback_object *obj, 579bf215546Sopenharmony_ci GLuint stream, 580bf215546Sopenharmony_ci GLsizei numInstances) 581bf215546Sopenharmony_ci{ 582bf215546Sopenharmony_ci GLenum error; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci /* From the GL 4.5 specification, page 429: 585bf215546Sopenharmony_ci * "An INVALID_VALUE error is generated if id is not the name of a 586bf215546Sopenharmony_ci * transform feedback object." 587bf215546Sopenharmony_ci */ 588bf215546Sopenharmony_ci if (!obj || !obj->EverBound || stream >= ctx->Const.MaxVertexStreams || 589bf215546Sopenharmony_ci numInstances < 0) { 590bf215546Sopenharmony_ci error = GL_INVALID_VALUE; 591bf215546Sopenharmony_ci } else { 592bf215546Sopenharmony_ci error = _mesa_valid_prim_mode(ctx, mode); 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci if (!error) { 595bf215546Sopenharmony_ci if (!obj->EndedAnytime) 596bf215546Sopenharmony_ci error = GL_INVALID_OPERATION; 597bf215546Sopenharmony_ci } 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci if (error) 601bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawTransformFeedback*"); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci return !error; 604bf215546Sopenharmony_ci} 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_cistatic GLenum 607bf215546Sopenharmony_civalid_draw_indirect(struct gl_context *ctx, 608bf215546Sopenharmony_ci GLenum mode, const GLvoid *indirect, 609bf215546Sopenharmony_ci GLsizei size) 610bf215546Sopenharmony_ci{ 611bf215546Sopenharmony_ci const uint64_t end = (uint64_t) (uintptr_t) indirect + size; 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci /* OpenGL ES 3.1 spec. section 10.5: 614bf215546Sopenharmony_ci * 615bf215546Sopenharmony_ci * "DrawArraysIndirect requires that all data sourced for the 616bf215546Sopenharmony_ci * command, including the DrawArraysIndirectCommand 617bf215546Sopenharmony_ci * structure, be in buffer objects, and may not be called when 618bf215546Sopenharmony_ci * the default vertex array object is bound." 619bf215546Sopenharmony_ci */ 620bf215546Sopenharmony_ci if (ctx->API != API_OPENGL_COMPAT && 621bf215546Sopenharmony_ci ctx->Array.VAO == ctx->Array.DefaultVAO) 622bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci /* From OpenGL ES 3.1 spec. section 10.5: 625bf215546Sopenharmony_ci * "An INVALID_OPERATION error is generated if zero is bound to 626bf215546Sopenharmony_ci * VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled 627bf215546Sopenharmony_ci * vertex array." 628bf215546Sopenharmony_ci * 629bf215546Sopenharmony_ci * Here we check that for each enabled vertex array we have a vertex 630bf215546Sopenharmony_ci * buffer bound. 631bf215546Sopenharmony_ci */ 632bf215546Sopenharmony_ci if (_mesa_is_gles31(ctx) && 633bf215546Sopenharmony_ci ctx->Array.VAO->Enabled & ~ctx->Array.VAO->VertexAttribBufferMask) 634bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci GLenum error = _mesa_valid_prim_mode(ctx, mode); 637bf215546Sopenharmony_ci if (error) 638bf215546Sopenharmony_ci return error; 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci /* OpenGL ES 3.1 specification, section 10.5: 641bf215546Sopenharmony_ci * 642bf215546Sopenharmony_ci * "An INVALID_OPERATION error is generated if 643bf215546Sopenharmony_ci * transform feedback is active and not paused." 644bf215546Sopenharmony_ci * 645bf215546Sopenharmony_ci * The OES_geometry_shader spec says: 646bf215546Sopenharmony_ci * 647bf215546Sopenharmony_ci * On p. 250 in the errors section for the DrawArraysIndirect command, 648bf215546Sopenharmony_ci * and on p. 254 in the errors section for the DrawElementsIndirect 649bf215546Sopenharmony_ci * command, delete the errors which state: 650bf215546Sopenharmony_ci * 651bf215546Sopenharmony_ci * "An INVALID_OPERATION error is generated if transform feedback is 652bf215546Sopenharmony_ci * active and not paused." 653bf215546Sopenharmony_ci * 654bf215546Sopenharmony_ci * (thus allowing transform feedback to work with indirect draw commands). 655bf215546Sopenharmony_ci */ 656bf215546Sopenharmony_ci if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader && 657bf215546Sopenharmony_ci _mesa_is_xfb_active_and_unpaused(ctx)) 658bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci /* From OpenGL version 4.4. section 10.5 661bf215546Sopenharmony_ci * and OpenGL ES 3.1, section 10.6: 662bf215546Sopenharmony_ci * 663bf215546Sopenharmony_ci * "An INVALID_VALUE error is generated if indirect is not a 664bf215546Sopenharmony_ci * multiple of the size, in basic machine units, of uint." 665bf215546Sopenharmony_ci */ 666bf215546Sopenharmony_ci if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) 667bf215546Sopenharmony_ci return GL_INVALID_VALUE; 668bf215546Sopenharmony_ci 669bf215546Sopenharmony_ci if (!ctx->DrawIndirectBuffer) 670bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer)) 673bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci /* From the ARB_draw_indirect specification: 676bf215546Sopenharmony_ci * "An INVALID_OPERATION error is generated if the commands source data 677bf215546Sopenharmony_ci * beyond the end of the buffer object [...]" 678bf215546Sopenharmony_ci */ 679bf215546Sopenharmony_ci if (ctx->DrawIndirectBuffer->Size < end) 680bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ci return GL_NO_ERROR; 683bf215546Sopenharmony_ci} 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_cistatic inline GLenum 686bf215546Sopenharmony_civalid_draw_indirect_elements(struct gl_context *ctx, 687bf215546Sopenharmony_ci GLenum mode, GLenum type, const GLvoid *indirect, 688bf215546Sopenharmony_ci GLsizeiptr size) 689bf215546Sopenharmony_ci{ 690bf215546Sopenharmony_ci GLenum error = valid_elements_type(ctx, type); 691bf215546Sopenharmony_ci if (error) 692bf215546Sopenharmony_ci return error; 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci /* 695bf215546Sopenharmony_ci * Unlike regular DrawElementsInstancedBaseVertex commands, the indices 696bf215546Sopenharmony_ci * may not come from a client array and must come from an index buffer. 697bf215546Sopenharmony_ci * If no element array buffer is bound, an INVALID_OPERATION error is 698bf215546Sopenharmony_ci * generated. 699bf215546Sopenharmony_ci */ 700bf215546Sopenharmony_ci if (!ctx->Array.VAO->IndexBufferObj) 701bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci return valid_draw_indirect(ctx, mode, indirect, size); 704bf215546Sopenharmony_ci} 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_cistatic GLboolean 707bf215546Sopenharmony_ci_mesa_valid_draw_indirect_multi(struct gl_context *ctx, 708bf215546Sopenharmony_ci GLsizei primcount, GLsizei stride, 709bf215546Sopenharmony_ci const char *name) 710bf215546Sopenharmony_ci{ 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci /* From the ARB_multi_draw_indirect specification: 713bf215546Sopenharmony_ci * "INVALID_VALUE is generated by MultiDrawArraysIndirect or 714bf215546Sopenharmony_ci * MultiDrawElementsIndirect if <primcount> is negative." 715bf215546Sopenharmony_ci * 716bf215546Sopenharmony_ci * "<primcount> must be positive, otherwise an INVALID_VALUE error will 717bf215546Sopenharmony_ci * be generated." 718bf215546Sopenharmony_ci */ 719bf215546Sopenharmony_ci if (primcount < 0) { 720bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name); 721bf215546Sopenharmony_ci return GL_FALSE; 722bf215546Sopenharmony_ci } 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci /* From the ARB_multi_draw_indirect specification: 726bf215546Sopenharmony_ci * "<stride> must be a multiple of four, otherwise an INVALID_VALUE 727bf215546Sopenharmony_ci * error is generated." 728bf215546Sopenharmony_ci */ 729bf215546Sopenharmony_ci if (stride % 4) { 730bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name); 731bf215546Sopenharmony_ci return GL_FALSE; 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci return GL_TRUE; 735bf215546Sopenharmony_ci} 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_cistatic GLboolean 738bf215546Sopenharmony_ci_mesa_validate_DrawArraysIndirect(struct gl_context *ctx, 739bf215546Sopenharmony_ci GLenum mode, 740bf215546Sopenharmony_ci const GLvoid *indirect) 741bf215546Sopenharmony_ci{ 742bf215546Sopenharmony_ci const unsigned drawArraysNumParams = 4; 743bf215546Sopenharmony_ci GLenum error = 744bf215546Sopenharmony_ci valid_draw_indirect(ctx, mode, indirect, 745bf215546Sopenharmony_ci drawArraysNumParams * sizeof(GLuint)); 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci if (error) 748bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawArraysIndirect"); 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci return !error; 751bf215546Sopenharmony_ci} 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_cistatic GLboolean 754bf215546Sopenharmony_ci_mesa_validate_DrawElementsIndirect(struct gl_context *ctx, 755bf215546Sopenharmony_ci GLenum mode, GLenum type, 756bf215546Sopenharmony_ci const GLvoid *indirect) 757bf215546Sopenharmony_ci{ 758bf215546Sopenharmony_ci const unsigned drawElementsNumParams = 5; 759bf215546Sopenharmony_ci GLenum error = valid_draw_indirect_elements(ctx, mode, type, indirect, 760bf215546Sopenharmony_ci drawElementsNumParams * 761bf215546Sopenharmony_ci sizeof(GLuint)); 762bf215546Sopenharmony_ci if (error) 763bf215546Sopenharmony_ci _mesa_error(ctx, error, "glDrawElementsIndirect"); 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci return !error; 766bf215546Sopenharmony_ci} 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_cistatic GLboolean 769bf215546Sopenharmony_ci_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx, 770bf215546Sopenharmony_ci GLenum mode, 771bf215546Sopenharmony_ci const GLvoid *indirect, 772bf215546Sopenharmony_ci GLsizei primcount, GLsizei stride) 773bf215546Sopenharmony_ci{ 774bf215546Sopenharmony_ci GLsizeiptr size = 0; 775bf215546Sopenharmony_ci const unsigned drawArraysNumParams = 4; 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */ 778bf215546Sopenharmony_ci assert(stride != 0); 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, 781bf215546Sopenharmony_ci "glMultiDrawArraysIndirect")) 782bf215546Sopenharmony_ci return GL_FALSE; 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ci /* number of bytes of the indirect buffer which will be read */ 785bf215546Sopenharmony_ci size = primcount 786bf215546Sopenharmony_ci ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint) 787bf215546Sopenharmony_ci : 0; 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci GLenum error = valid_draw_indirect(ctx, mode, indirect, size); 790bf215546Sopenharmony_ci if (error) 791bf215546Sopenharmony_ci _mesa_error(ctx, error, "glMultiDrawArraysIndirect"); 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ci return !error; 794bf215546Sopenharmony_ci} 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_cistatic GLboolean 797bf215546Sopenharmony_ci_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx, 798bf215546Sopenharmony_ci GLenum mode, GLenum type, 799bf215546Sopenharmony_ci const GLvoid *indirect, 800bf215546Sopenharmony_ci GLsizei primcount, GLsizei stride) 801bf215546Sopenharmony_ci{ 802bf215546Sopenharmony_ci GLsizeiptr size = 0; 803bf215546Sopenharmony_ci const unsigned drawElementsNumParams = 5; 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_ci /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */ 806bf215546Sopenharmony_ci assert(stride != 0); 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, 809bf215546Sopenharmony_ci "glMultiDrawElementsIndirect")) 810bf215546Sopenharmony_ci return GL_FALSE; 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci /* number of bytes of the indirect buffer which will be read */ 813bf215546Sopenharmony_ci size = primcount 814bf215546Sopenharmony_ci ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint) 815bf215546Sopenharmony_ci : 0; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci GLenum error = valid_draw_indirect_elements(ctx, mode, type, indirect, 818bf215546Sopenharmony_ci size); 819bf215546Sopenharmony_ci if (error) 820bf215546Sopenharmony_ci _mesa_error(ctx, error, "glMultiDrawElementsIndirect"); 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci return !error; 823bf215546Sopenharmony_ci} 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_cistatic GLenum 826bf215546Sopenharmony_civalid_draw_indirect_parameters(struct gl_context *ctx, 827bf215546Sopenharmony_ci GLintptr drawcount) 828bf215546Sopenharmony_ci{ 829bf215546Sopenharmony_ci /* From the ARB_indirect_parameters specification: 830bf215546Sopenharmony_ci * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or 831bf215546Sopenharmony_ci * MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of 832bf215546Sopenharmony_ci * four." 833bf215546Sopenharmony_ci */ 834bf215546Sopenharmony_ci if (drawcount & 3) 835bf215546Sopenharmony_ci return GL_INVALID_VALUE; 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci /* From the ARB_indirect_parameters specification: 838bf215546Sopenharmony_ci * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or 839bf215546Sopenharmony_ci * MultiDrawElementsIndirectCountARB if no buffer is bound to the 840bf215546Sopenharmony_ci * PARAMETER_BUFFER_ARB binding point." 841bf215546Sopenharmony_ci */ 842bf215546Sopenharmony_ci if (!ctx->ParameterBuffer) 843bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer)) 846bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci /* From the ARB_indirect_parameters specification: 849bf215546Sopenharmony_ci * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or 850bf215546Sopenharmony_ci * MultiDrawElementsIndirectCountARB if reading a <sizei> typed value 851bf215546Sopenharmony_ci * from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset 852bf215546Sopenharmony_ci * specified by <drawcount> would result in an out-of-bounds access." 853bf215546Sopenharmony_ci */ 854bf215546Sopenharmony_ci if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei)) 855bf215546Sopenharmony_ci return GL_INVALID_OPERATION; 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci return GL_NO_ERROR; 858bf215546Sopenharmony_ci} 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_cistatic GLboolean 861bf215546Sopenharmony_ci_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx, 862bf215546Sopenharmony_ci GLenum mode, 863bf215546Sopenharmony_ci GLintptr indirect, 864bf215546Sopenharmony_ci GLintptr drawcount, 865bf215546Sopenharmony_ci GLsizei maxdrawcount, 866bf215546Sopenharmony_ci GLsizei stride) 867bf215546Sopenharmony_ci{ 868bf215546Sopenharmony_ci GLsizeiptr size = 0; 869bf215546Sopenharmony_ci const unsigned drawArraysNumParams = 4; 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */ 872bf215546Sopenharmony_ci assert(stride != 0); 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride, 875bf215546Sopenharmony_ci "glMultiDrawArraysIndirectCountARB")) 876bf215546Sopenharmony_ci return GL_FALSE; 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci /* number of bytes of the indirect buffer which will be read */ 879bf215546Sopenharmony_ci size = maxdrawcount 880bf215546Sopenharmony_ci ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint) 881bf215546Sopenharmony_ci : 0; 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_ci GLenum error = valid_draw_indirect(ctx, mode, (void *)indirect, size); 884bf215546Sopenharmony_ci if (!error) 885bf215546Sopenharmony_ci error = valid_draw_indirect_parameters(ctx, drawcount); 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci if (error) 888bf215546Sopenharmony_ci _mesa_error(ctx, error, "glMultiDrawArraysIndirectCountARB"); 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci return !error; 891bf215546Sopenharmony_ci} 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_cistatic GLboolean 894bf215546Sopenharmony_ci_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx, 895bf215546Sopenharmony_ci GLenum mode, GLenum type, 896bf215546Sopenharmony_ci GLintptr indirect, 897bf215546Sopenharmony_ci GLintptr drawcount, 898bf215546Sopenharmony_ci GLsizei maxdrawcount, 899bf215546Sopenharmony_ci GLsizei stride) 900bf215546Sopenharmony_ci{ 901bf215546Sopenharmony_ci GLsizeiptr size = 0; 902bf215546Sopenharmony_ci const unsigned drawElementsNumParams = 5; 903bf215546Sopenharmony_ci 904bf215546Sopenharmony_ci /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */ 905bf215546Sopenharmony_ci assert(stride != 0); 906bf215546Sopenharmony_ci 907bf215546Sopenharmony_ci if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride, 908bf215546Sopenharmony_ci "glMultiDrawElementsIndirectCountARB")) 909bf215546Sopenharmony_ci return GL_FALSE; 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci /* number of bytes of the indirect buffer which will be read */ 912bf215546Sopenharmony_ci size = maxdrawcount 913bf215546Sopenharmony_ci ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint) 914bf215546Sopenharmony_ci : 0; 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci GLenum error = valid_draw_indirect_elements(ctx, mode, type, 917bf215546Sopenharmony_ci (void *)indirect, size); 918bf215546Sopenharmony_ci if (!error) 919bf215546Sopenharmony_ci error = valid_draw_indirect_parameters(ctx, drawcount); 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci if (error) 922bf215546Sopenharmony_ci _mesa_error(ctx, error, "glMultiDrawElementsIndirectCountARB"); 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_ci return !error; 925bf215546Sopenharmony_ci} 926bf215546Sopenharmony_ci 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_ci#define MAX_ALLOCA_PRIMS(prim) (50000 / sizeof(*prim)) 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_ci/* Use calloc for large allocations and alloca for small allocations. */ 931bf215546Sopenharmony_ci/* We have to use a macro because alloca is local within the function. */ 932bf215546Sopenharmony_ci#define ALLOC_PRIMS(prim, primcount, func) do { \ 933bf215546Sopenharmony_ci if (unlikely(primcount > MAX_ALLOCA_PRIMS(prim))) { \ 934bf215546Sopenharmony_ci prim = calloc(primcount, sizeof(*prim)); \ 935bf215546Sopenharmony_ci if (!prim) { \ 936bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, func); \ 937bf215546Sopenharmony_ci return; \ 938bf215546Sopenharmony_ci } \ 939bf215546Sopenharmony_ci } else { \ 940bf215546Sopenharmony_ci prim = alloca(primcount * sizeof(*prim)); \ 941bf215546Sopenharmony_ci } \ 942bf215546Sopenharmony_ci} while (0) 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci#define FREE_PRIMS(prim, primcount) do { \ 945bf215546Sopenharmony_ci if (primcount > MAX_ALLOCA_PRIMS(prim)) \ 946bf215546Sopenharmony_ci free(prim); \ 947bf215546Sopenharmony_ci} while (0) 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci 950bf215546Sopenharmony_ci/** 951bf215546Sopenharmony_ci * Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw. 952bf215546Sopenharmony_ci */ 953bf215546Sopenharmony_civoid 954bf215546Sopenharmony_ci_mesa_draw_gallium_fallback(struct gl_context *ctx, 955bf215546Sopenharmony_ci struct pipe_draw_info *info, 956bf215546Sopenharmony_ci unsigned drawid_offset, 957bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 958bf215546Sopenharmony_ci unsigned num_draws) 959bf215546Sopenharmony_ci{ 960bf215546Sopenharmony_ci struct _mesa_index_buffer ib; 961bf215546Sopenharmony_ci unsigned index_size = info->index_size; 962bf215546Sopenharmony_ci unsigned min_index = 0, max_index = ~0u; 963bf215546Sopenharmony_ci bool index_bounds_valid = false; 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci if (!info->instance_count) 966bf215546Sopenharmony_ci return; 967bf215546Sopenharmony_ci 968bf215546Sopenharmony_ci if (index_size) { 969bf215546Sopenharmony_ci if (info->index_bounds_valid) { 970bf215546Sopenharmony_ci min_index = info->min_index; 971bf215546Sopenharmony_ci max_index = info->max_index; 972bf215546Sopenharmony_ci index_bounds_valid = true; 973bf215546Sopenharmony_ci } 974bf215546Sopenharmony_ci } else { 975bf215546Sopenharmony_ci /* The index_bounds_valid field and min/max_index are not used for 976bf215546Sopenharmony_ci * non-indexed draw calls (they are undefined), but classic drivers 977bf215546Sopenharmony_ci * need the index bounds. They will be computed manually. 978bf215546Sopenharmony_ci */ 979bf215546Sopenharmony_ci index_bounds_valid = true; 980bf215546Sopenharmony_ci } 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci ib.index_size_shift = util_logbase2(index_size); 983bf215546Sopenharmony_ci 984bf215546Sopenharmony_ci /* Single draw or a fallback for user indices. */ 985bf215546Sopenharmony_ci if (num_draws == 1) { 986bf215546Sopenharmony_ci if (!draws[0].count) 987bf215546Sopenharmony_ci return; 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci if (index_size) { 990bf215546Sopenharmony_ci ib.count = draws[0].count; 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci if (info->has_user_indices) { 993bf215546Sopenharmony_ci ib.obj = NULL; 994bf215546Sopenharmony_ci ib.ptr = (const char*)info->index.user; 995bf215546Sopenharmony_ci } else { 996bf215546Sopenharmony_ci ib.obj = info->index.gl_bo; 997bf215546Sopenharmony_ci ib.ptr = NULL; 998bf215546Sopenharmony_ci } 999bf215546Sopenharmony_ci } 1000bf215546Sopenharmony_ci 1001bf215546Sopenharmony_ci struct _mesa_prim prim; 1002bf215546Sopenharmony_ci prim.mode = info->mode; 1003bf215546Sopenharmony_ci prim.begin = 1; 1004bf215546Sopenharmony_ci prim.end = 1; 1005bf215546Sopenharmony_ci prim.start = draws[0].start; 1006bf215546Sopenharmony_ci prim.count = draws[0].count; 1007bf215546Sopenharmony_ci prim.basevertex = index_size ? draws[0].index_bias : 0; 1008bf215546Sopenharmony_ci prim.draw_id = drawid_offset; 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci if (!index_size) { 1011bf215546Sopenharmony_ci min_index = draws[0].start; 1012bf215546Sopenharmony_ci max_index = draws[0].start + draws[0].count - 1; 1013bf215546Sopenharmony_ci } 1014bf215546Sopenharmony_ci 1015bf215546Sopenharmony_ci st_feedback_draw_vbo(ctx, &prim, 1, index_size ? &ib : NULL, 1016bf215546Sopenharmony_ci index_bounds_valid, info->primitive_restart, 1017bf215546Sopenharmony_ci info->restart_index, min_index, max_index, 1018bf215546Sopenharmony_ci info->instance_count, info->start_instance); 1019bf215546Sopenharmony_ci return; 1020bf215546Sopenharmony_ci } 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_ci struct _mesa_prim *prim; 1023bf215546Sopenharmony_ci unsigned max_count = 0; 1024bf215546Sopenharmony_ci unsigned num_prims = 0; 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci ALLOC_PRIMS(prim, num_draws, "DrawGallium"); 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci min_index = ~0u; 1029bf215546Sopenharmony_ci max_index = 0; 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ci for (unsigned i = 0; i < num_draws; i++) { 1032bf215546Sopenharmony_ci if (!draws[i].count) 1033bf215546Sopenharmony_ci continue; 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_ci prim[num_prims].mode = info->mode; 1036bf215546Sopenharmony_ci prim[num_prims].begin = 1; 1037bf215546Sopenharmony_ci prim[num_prims].end = 1; 1038bf215546Sopenharmony_ci prim[num_prims].start = draws[i].start; 1039bf215546Sopenharmony_ci prim[num_prims].count = draws[i].count; 1040bf215546Sopenharmony_ci prim[num_prims].basevertex = info->index_size ? draws[i].index_bias : 0; 1041bf215546Sopenharmony_ci prim[num_prims].draw_id = drawid_offset + (info->increment_draw_id ? i : 0); 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci if (!index_size) { 1044bf215546Sopenharmony_ci min_index = MIN2(min_index, draws[i].start); 1045bf215546Sopenharmony_ci max_index = MAX2(max_index, draws[i].start + draws[i].count - 1); 1046bf215546Sopenharmony_ci } 1047bf215546Sopenharmony_ci 1048bf215546Sopenharmony_ci max_count = MAX2(max_count, prim[num_prims].count); 1049bf215546Sopenharmony_ci num_prims++; 1050bf215546Sopenharmony_ci } 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci if (info->index_size) { 1053bf215546Sopenharmony_ci ib.count = max_count; 1054bf215546Sopenharmony_ci ib.index_size_shift = util_logbase2(index_size); 1055bf215546Sopenharmony_ci 1056bf215546Sopenharmony_ci if (info->has_user_indices) { 1057bf215546Sopenharmony_ci ib.obj = NULL; 1058bf215546Sopenharmony_ci ib.ptr = (const char*)info->index.user; 1059bf215546Sopenharmony_ci } else { 1060bf215546Sopenharmony_ci ib.obj = info->index.gl_bo; 1061bf215546Sopenharmony_ci ib.ptr = NULL; 1062bf215546Sopenharmony_ci } 1063bf215546Sopenharmony_ci } 1064bf215546Sopenharmony_ci 1065bf215546Sopenharmony_ci if (num_prims) 1066bf215546Sopenharmony_ci st_feedback_draw_vbo(ctx, prim, num_prims, index_size ? &ib : NULL, 1067bf215546Sopenharmony_ci index_bounds_valid, info->primitive_restart, 1068bf215546Sopenharmony_ci info->restart_index, min_index, max_index, 1069bf215546Sopenharmony_ci info->instance_count, info->start_instance); 1070bf215546Sopenharmony_ci FREE_PRIMS(prim, num_draws); 1071bf215546Sopenharmony_ci} 1072bf215546Sopenharmony_ci 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci/** 1075bf215546Sopenharmony_ci * Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw. 1076bf215546Sopenharmony_ci */ 1077bf215546Sopenharmony_civoid 1078bf215546Sopenharmony_ci_mesa_draw_gallium_multimode_fallback(struct gl_context *ctx, 1079bf215546Sopenharmony_ci struct pipe_draw_info *info, 1080bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 1081bf215546Sopenharmony_ci const unsigned char *mode, 1082bf215546Sopenharmony_ci unsigned num_draws) 1083bf215546Sopenharmony_ci{ 1084bf215546Sopenharmony_ci unsigned i, first; 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_ci /* Find consecutive draws where mode doesn't vary. */ 1087bf215546Sopenharmony_ci for (i = 0, first = 0; i <= num_draws; i++) { 1088bf215546Sopenharmony_ci if (i == num_draws || mode[i] != mode[first]) { 1089bf215546Sopenharmony_ci info->mode = mode[first]; 1090bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, info, 0, &draws[first], i - first); 1091bf215546Sopenharmony_ci first = i; 1092bf215546Sopenharmony_ci } 1093bf215546Sopenharmony_ci } 1094bf215546Sopenharmony_ci} 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_ci/** 1097bf215546Sopenharmony_ci * Check that element 'j' of the array has reasonable data. 1098bf215546Sopenharmony_ci * Map VBO if needed. 1099bf215546Sopenharmony_ci * For debugging purposes; not normally used. 1100bf215546Sopenharmony_ci */ 1101bf215546Sopenharmony_cistatic void 1102bf215546Sopenharmony_cicheck_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao, 1103bf215546Sopenharmony_ci GLuint attrib, GLuint j) 1104bf215546Sopenharmony_ci{ 1105bf215546Sopenharmony_ci const struct gl_array_attributes *array = &vao->VertexAttrib[attrib]; 1106bf215546Sopenharmony_ci if (vao->Enabled & VERT_BIT(attrib)) { 1107bf215546Sopenharmony_ci const struct gl_vertex_buffer_binding *binding = 1108bf215546Sopenharmony_ci &vao->BufferBinding[array->BufferBindingIndex]; 1109bf215546Sopenharmony_ci struct gl_buffer_object *bo = binding->BufferObj; 1110bf215546Sopenharmony_ci const void *data = array->Ptr; 1111bf215546Sopenharmony_ci if (bo) { 1112bf215546Sopenharmony_ci data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding), 1113bf215546Sopenharmony_ci bo->Mappings[MAP_INTERNAL].Pointer); 1114bf215546Sopenharmony_ci } 1115bf215546Sopenharmony_ci switch (array->Format.Type) { 1116bf215546Sopenharmony_ci case GL_FLOAT: 1117bf215546Sopenharmony_ci { 1118bf215546Sopenharmony_ci GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j); 1119bf215546Sopenharmony_ci GLint k; 1120bf215546Sopenharmony_ci for (k = 0; k < array->Format.Size; k++) { 1121bf215546Sopenharmony_ci if (util_is_inf_or_nan(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) { 1122bf215546Sopenharmony_ci printf("Bad array data:\n"); 1123bf215546Sopenharmony_ci printf(" Element[%u].%u = %f\n", j, k, f[k]); 1124bf215546Sopenharmony_ci printf(" Array %u at %p\n", attrib, (void *) array); 1125bf215546Sopenharmony_ci printf(" Type 0x%x, Size %d, Stride %d\n", 1126bf215546Sopenharmony_ci array->Format.Type, array->Format.Size, 1127bf215546Sopenharmony_ci binding->Stride); 1128bf215546Sopenharmony_ci printf(" Address/offset %p in Buffer Object %u\n", 1129bf215546Sopenharmony_ci array->Ptr, bo ? bo->Name : 0); 1130bf215546Sopenharmony_ci f[k] = 1.0F; /* XXX replace the bad value! */ 1131bf215546Sopenharmony_ci } 1132bf215546Sopenharmony_ci /*assert(!util_is_inf_or_nan(f[k])); */ 1133bf215546Sopenharmony_ci } 1134bf215546Sopenharmony_ci } 1135bf215546Sopenharmony_ci break; 1136bf215546Sopenharmony_ci default: 1137bf215546Sopenharmony_ci ; 1138bf215546Sopenharmony_ci } 1139bf215546Sopenharmony_ci } 1140bf215546Sopenharmony_ci} 1141bf215546Sopenharmony_ci 1142bf215546Sopenharmony_ci 1143bf215546Sopenharmony_cistatic inline unsigned 1144bf215546Sopenharmony_ciget_index_size_shift(GLenum type) 1145bf215546Sopenharmony_ci{ 1146bf215546Sopenharmony_ci /* The type is already validated, so use a fast conversion. 1147bf215546Sopenharmony_ci * 1148bf215546Sopenharmony_ci * GL_UNSIGNED_BYTE - GL_UNSIGNED_BYTE = 0 1149bf215546Sopenharmony_ci * GL_UNSIGNED_SHORT - GL_UNSIGNED_BYTE = 2 1150bf215546Sopenharmony_ci * GL_UNSIGNED_INT - GL_UNSIGNED_BYTE = 4 1151bf215546Sopenharmony_ci * 1152bf215546Sopenharmony_ci * Divide by 2 to get 0,1,2. 1153bf215546Sopenharmony_ci */ 1154bf215546Sopenharmony_ci return (type - GL_UNSIGNED_BYTE) >> 1; 1155bf215546Sopenharmony_ci} 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci/** 1158bf215546Sopenharmony_ci * Examine the array's data for NaNs, etc. 1159bf215546Sopenharmony_ci * For debug purposes; not normally used. 1160bf215546Sopenharmony_ci */ 1161bf215546Sopenharmony_cistatic void 1162bf215546Sopenharmony_cicheck_draw_elements_data(struct gl_context *ctx, GLsizei count, 1163bf215546Sopenharmony_ci GLenum elemType, const void *elements, 1164bf215546Sopenharmony_ci GLint basevertex) 1165bf215546Sopenharmony_ci{ 1166bf215546Sopenharmony_ci struct gl_vertex_array_object *vao = ctx->Array.VAO; 1167bf215546Sopenharmony_ci GLint i; 1168bf215546Sopenharmony_ci GLuint k; 1169bf215546Sopenharmony_ci 1170bf215546Sopenharmony_ci _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT); 1171bf215546Sopenharmony_ci 1172bf215546Sopenharmony_ci if (vao->IndexBufferObj) 1173bf215546Sopenharmony_ci elements = 1174bf215546Sopenharmony_ci ADD_POINTERS(vao->IndexBufferObj->Mappings[MAP_INTERNAL].Pointer, elements); 1175bf215546Sopenharmony_ci 1176bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 1177bf215546Sopenharmony_ci GLuint j; 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci /* j = element[i] */ 1180bf215546Sopenharmony_ci switch (elemType) { 1181bf215546Sopenharmony_ci case GL_UNSIGNED_BYTE: 1182bf215546Sopenharmony_ci j = ((const GLubyte *) elements)[i]; 1183bf215546Sopenharmony_ci break; 1184bf215546Sopenharmony_ci case GL_UNSIGNED_SHORT: 1185bf215546Sopenharmony_ci j = ((const GLushort *) elements)[i]; 1186bf215546Sopenharmony_ci break; 1187bf215546Sopenharmony_ci case GL_UNSIGNED_INT: 1188bf215546Sopenharmony_ci j = ((const GLuint *) elements)[i]; 1189bf215546Sopenharmony_ci break; 1190bf215546Sopenharmony_ci default: 1191bf215546Sopenharmony_ci unreachable("Unexpected index buffer type"); 1192bf215546Sopenharmony_ci } 1193bf215546Sopenharmony_ci 1194bf215546Sopenharmony_ci /* check element j of each enabled array */ 1195bf215546Sopenharmony_ci for (k = 0; k < VERT_ATTRIB_MAX; k++) { 1196bf215546Sopenharmony_ci check_array_data(ctx, vao, k, j); 1197bf215546Sopenharmony_ci } 1198bf215546Sopenharmony_ci } 1199bf215546Sopenharmony_ci 1200bf215546Sopenharmony_ci _mesa_vao_unmap(ctx, vao); 1201bf215546Sopenharmony_ci} 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci/** 1205bf215546Sopenharmony_ci * Check array data, looking for NaNs, etc. 1206bf215546Sopenharmony_ci */ 1207bf215546Sopenharmony_cistatic void 1208bf215546Sopenharmony_cicheck_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count) 1209bf215546Sopenharmony_ci{ 1210bf215546Sopenharmony_ci /* TO DO */ 1211bf215546Sopenharmony_ci} 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci 1214bf215546Sopenharmony_ci/** 1215bf215546Sopenharmony_ci * Print info/data for glDrawArrays(), for debugging. 1216bf215546Sopenharmony_ci */ 1217bf215546Sopenharmony_cistatic void 1218bf215546Sopenharmony_ciprint_draw_arrays(struct gl_context *ctx, 1219bf215546Sopenharmony_ci GLenum mode, GLint start, GLsizei count) 1220bf215546Sopenharmony_ci{ 1221bf215546Sopenharmony_ci struct gl_vertex_array_object *vao = ctx->Array.VAO; 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci printf("_mesa_DrawArrays(mode 0x%x, start %d, count %d):\n", 1224bf215546Sopenharmony_ci mode, start, count); 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT); 1227bf215546Sopenharmony_ci 1228bf215546Sopenharmony_ci GLbitfield mask = vao->Enabled; 1229bf215546Sopenharmony_ci while (mask) { 1230bf215546Sopenharmony_ci const gl_vert_attrib i = u_bit_scan(&mask); 1231bf215546Sopenharmony_ci const struct gl_array_attributes *array = &vao->VertexAttrib[i]; 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci const struct gl_vertex_buffer_binding *binding = 1234bf215546Sopenharmony_ci &vao->BufferBinding[array->BufferBindingIndex]; 1235bf215546Sopenharmony_ci struct gl_buffer_object *bufObj = binding->BufferObj; 1236bf215546Sopenharmony_ci 1237bf215546Sopenharmony_ci printf("attr %s: size %d stride %d " 1238bf215546Sopenharmony_ci "ptr %p Bufobj %u\n", 1239bf215546Sopenharmony_ci gl_vert_attrib_name((gl_vert_attrib) i), 1240bf215546Sopenharmony_ci array->Format.Size, binding->Stride, 1241bf215546Sopenharmony_ci array->Ptr, bufObj ? bufObj->Name : 0); 1242bf215546Sopenharmony_ci 1243bf215546Sopenharmony_ci if (bufObj) { 1244bf215546Sopenharmony_ci GLubyte *p = bufObj->Mappings[MAP_INTERNAL].Pointer; 1245bf215546Sopenharmony_ci int offset = (int) (GLintptr) 1246bf215546Sopenharmony_ci _mesa_vertex_attrib_address(array, binding); 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci unsigned multiplier; 1249bf215546Sopenharmony_ci switch (array->Format.Type) { 1250bf215546Sopenharmony_ci case GL_DOUBLE: 1251bf215546Sopenharmony_ci case GL_INT64_ARB: 1252bf215546Sopenharmony_ci case GL_UNSIGNED_INT64_ARB: 1253bf215546Sopenharmony_ci multiplier = 2; 1254bf215546Sopenharmony_ci break; 1255bf215546Sopenharmony_ci default: 1256bf215546Sopenharmony_ci multiplier = 1; 1257bf215546Sopenharmony_ci } 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci float *f = (float *) (p + offset); 1260bf215546Sopenharmony_ci int *k = (int *) f; 1261bf215546Sopenharmony_ci int i = 0; 1262bf215546Sopenharmony_ci int n = (count - 1) * (binding->Stride / (4 * multiplier)) 1263bf215546Sopenharmony_ci + array->Format.Size; 1264bf215546Sopenharmony_ci if (n > 32) 1265bf215546Sopenharmony_ci n = 32; 1266bf215546Sopenharmony_ci printf(" Data at offset %d:\n", offset); 1267bf215546Sopenharmony_ci do { 1268bf215546Sopenharmony_ci if (multiplier == 2) 1269bf215546Sopenharmony_ci printf(" double[%d] = 0x%016llx %lf\n", i, 1270bf215546Sopenharmony_ci ((unsigned long long *) k)[i], ((double *) f)[i]); 1271bf215546Sopenharmony_ci else 1272bf215546Sopenharmony_ci printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); 1273bf215546Sopenharmony_ci i++; 1274bf215546Sopenharmony_ci } while (i < n); 1275bf215546Sopenharmony_ci } 1276bf215546Sopenharmony_ci } 1277bf215546Sopenharmony_ci 1278bf215546Sopenharmony_ci _mesa_vao_unmap_arrays(ctx, vao); 1279bf215546Sopenharmony_ci} 1280bf215546Sopenharmony_ci 1281bf215546Sopenharmony_ci 1282bf215546Sopenharmony_ci/** 1283bf215546Sopenharmony_ci * Helper function called by the other DrawArrays() functions below. 1284bf215546Sopenharmony_ci * This is where we handle primitive restart for drawing non-indexed 1285bf215546Sopenharmony_ci * arrays. If primitive restart is enabled, it typically means 1286bf215546Sopenharmony_ci * splitting one DrawArrays() into two. 1287bf215546Sopenharmony_ci */ 1288bf215546Sopenharmony_cistatic void 1289bf215546Sopenharmony_ci_mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, 1290bf215546Sopenharmony_ci GLsizei count, GLuint numInstances, GLuint baseInstance) 1291bf215546Sopenharmony_ci{ 1292bf215546Sopenharmony_ci /* Viewperf has many draws with count=0. Discarding them is faster than 1293bf215546Sopenharmony_ci * processing them. 1294bf215546Sopenharmony_ci */ 1295bf215546Sopenharmony_ci if (!count || !numInstances) 1296bf215546Sopenharmony_ci return; 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci /* OpenGL 4.5 says that primitive restart is ignored with non-indexed 1299bf215546Sopenharmony_ci * draws. 1300bf215546Sopenharmony_ci */ 1301bf215546Sopenharmony_ci struct pipe_draw_info info; 1302bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_ci info.mode = mode; 1305bf215546Sopenharmony_ci info.index_size = 0; 1306bf215546Sopenharmony_ci /* Packed section begin. */ 1307bf215546Sopenharmony_ci info.primitive_restart = false; 1308bf215546Sopenharmony_ci info.has_user_indices = false; 1309bf215546Sopenharmony_ci info.index_bounds_valid = true; 1310bf215546Sopenharmony_ci info.increment_draw_id = false; 1311bf215546Sopenharmony_ci info.was_line_loop = false; 1312bf215546Sopenharmony_ci info.take_index_buffer_ownership = false; 1313bf215546Sopenharmony_ci info.index_bias_varies = false; 1314bf215546Sopenharmony_ci /* Packed section end. */ 1315bf215546Sopenharmony_ci info.start_instance = baseInstance; 1316bf215546Sopenharmony_ci info.instance_count = numInstances; 1317bf215546Sopenharmony_ci info.view_mask = 0; 1318bf215546Sopenharmony_ci info.min_index = start; 1319bf215546Sopenharmony_ci info.max_index = start + count - 1; 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci draw.start = start; 1322bf215546Sopenharmony_ci draw.count = count; 1323bf215546Sopenharmony_ci 1324bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, 0, &draw, 1); 1325bf215546Sopenharmony_ci 1326bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 1327bf215546Sopenharmony_ci _mesa_flush(ctx); 1328bf215546Sopenharmony_ci } 1329bf215546Sopenharmony_ci} 1330bf215546Sopenharmony_ci 1331bf215546Sopenharmony_ci 1332bf215546Sopenharmony_ci/** 1333bf215546Sopenharmony_ci * Execute a glRectf() function. 1334bf215546Sopenharmony_ci */ 1335bf215546Sopenharmony_civoid GLAPIENTRY 1336bf215546Sopenharmony_ci_mesa_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) 1337bf215546Sopenharmony_ci{ 1338bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1339bf215546Sopenharmony_ci ASSERT_OUTSIDE_BEGIN_END(ctx); 1340bf215546Sopenharmony_ci 1341bf215546Sopenharmony_ci CALL_Begin(ctx->CurrentServerDispatch, (GL_QUADS)); 1342bf215546Sopenharmony_ci /* Begin can change CurrentServerDispatch. */ 1343bf215546Sopenharmony_ci struct _glapi_table *dispatch = ctx->CurrentServerDispatch; 1344bf215546Sopenharmony_ci CALL_Vertex2f(dispatch, (x1, y1)); 1345bf215546Sopenharmony_ci CALL_Vertex2f(dispatch, (x2, y1)); 1346bf215546Sopenharmony_ci CALL_Vertex2f(dispatch, (x2, y2)); 1347bf215546Sopenharmony_ci CALL_Vertex2f(dispatch, (x1, y2)); 1348bf215546Sopenharmony_ci CALL_End(dispatch, ()); 1349bf215546Sopenharmony_ci} 1350bf215546Sopenharmony_ci 1351bf215546Sopenharmony_ci 1352bf215546Sopenharmony_civoid GLAPIENTRY 1353bf215546Sopenharmony_ci_mesa_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) 1354bf215546Sopenharmony_ci{ 1355bf215546Sopenharmony_ci _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); 1356bf215546Sopenharmony_ci} 1357bf215546Sopenharmony_ci 1358bf215546Sopenharmony_civoid GLAPIENTRY 1359bf215546Sopenharmony_ci_mesa_Rectdv(const GLdouble *v1, const GLdouble *v2) 1360bf215546Sopenharmony_ci{ 1361bf215546Sopenharmony_ci _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); 1362bf215546Sopenharmony_ci} 1363bf215546Sopenharmony_ci 1364bf215546Sopenharmony_civoid GLAPIENTRY 1365bf215546Sopenharmony_ci_mesa_Rectfv(const GLfloat *v1, const GLfloat *v2) 1366bf215546Sopenharmony_ci{ 1367bf215546Sopenharmony_ci _mesa_Rectf(v1[0], v1[1], v2[0], v2[1]); 1368bf215546Sopenharmony_ci} 1369bf215546Sopenharmony_ci 1370bf215546Sopenharmony_civoid GLAPIENTRY 1371bf215546Sopenharmony_ci_mesa_Recti(GLint x1, GLint y1, GLint x2, GLint y2) 1372bf215546Sopenharmony_ci{ 1373bf215546Sopenharmony_ci _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); 1374bf215546Sopenharmony_ci} 1375bf215546Sopenharmony_ci 1376bf215546Sopenharmony_civoid GLAPIENTRY 1377bf215546Sopenharmony_ci_mesa_Rectiv(const GLint *v1, const GLint *v2) 1378bf215546Sopenharmony_ci{ 1379bf215546Sopenharmony_ci _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); 1380bf215546Sopenharmony_ci} 1381bf215546Sopenharmony_ci 1382bf215546Sopenharmony_civoid GLAPIENTRY 1383bf215546Sopenharmony_ci_mesa_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) 1384bf215546Sopenharmony_ci{ 1385bf215546Sopenharmony_ci _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); 1386bf215546Sopenharmony_ci} 1387bf215546Sopenharmony_ci 1388bf215546Sopenharmony_civoid GLAPIENTRY 1389bf215546Sopenharmony_ci_mesa_Rectsv(const GLshort *v1, const GLshort *v2) 1390bf215546Sopenharmony_ci{ 1391bf215546Sopenharmony_ci _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); 1392bf215546Sopenharmony_ci} 1393bf215546Sopenharmony_ci 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_civoid GLAPIENTRY 1396bf215546Sopenharmony_ci_mesa_EvalMesh1(GLenum mode, GLint i1, GLint i2) 1397bf215546Sopenharmony_ci{ 1398bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1399bf215546Sopenharmony_ci GLint i; 1400bf215546Sopenharmony_ci GLfloat u, du; 1401bf215546Sopenharmony_ci GLenum prim; 1402bf215546Sopenharmony_ci 1403bf215546Sopenharmony_ci switch (mode) { 1404bf215546Sopenharmony_ci case GL_POINT: 1405bf215546Sopenharmony_ci prim = GL_POINTS; 1406bf215546Sopenharmony_ci break; 1407bf215546Sopenharmony_ci case GL_LINE: 1408bf215546Sopenharmony_ci prim = GL_LINE_STRIP; 1409bf215546Sopenharmony_ci break; 1410bf215546Sopenharmony_ci default: 1411bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)"); 1412bf215546Sopenharmony_ci return; 1413bf215546Sopenharmony_ci } 1414bf215546Sopenharmony_ci 1415bf215546Sopenharmony_ci /* No effect if vertex maps disabled. 1416bf215546Sopenharmony_ci */ 1417bf215546Sopenharmony_ci if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) 1418bf215546Sopenharmony_ci return; 1419bf215546Sopenharmony_ci 1420bf215546Sopenharmony_ci du = ctx->Eval.MapGrid1du; 1421bf215546Sopenharmony_ci u = ctx->Eval.MapGrid1u1 + i1 * du; 1422bf215546Sopenharmony_ci 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci CALL_Begin(ctx->CurrentServerDispatch, (prim)); 1425bf215546Sopenharmony_ci /* Begin can change CurrentServerDispatch. */ 1426bf215546Sopenharmony_ci struct _glapi_table *dispatch = ctx->CurrentServerDispatch; 1427bf215546Sopenharmony_ci for (i = i1; i <= i2; i++, u += du) { 1428bf215546Sopenharmony_ci CALL_EvalCoord1f(dispatch, (u)); 1429bf215546Sopenharmony_ci } 1430bf215546Sopenharmony_ci CALL_End(dispatch, ()); 1431bf215546Sopenharmony_ci} 1432bf215546Sopenharmony_ci 1433bf215546Sopenharmony_ci 1434bf215546Sopenharmony_civoid GLAPIENTRY 1435bf215546Sopenharmony_ci_mesa_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) 1436bf215546Sopenharmony_ci{ 1437bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1438bf215546Sopenharmony_ci GLfloat u, du, v, dv, v1, u1; 1439bf215546Sopenharmony_ci GLint i, j; 1440bf215546Sopenharmony_ci 1441bf215546Sopenharmony_ci switch (mode) { 1442bf215546Sopenharmony_ci case GL_POINT: 1443bf215546Sopenharmony_ci case GL_LINE: 1444bf215546Sopenharmony_ci case GL_FILL: 1445bf215546Sopenharmony_ci break; 1446bf215546Sopenharmony_ci default: 1447bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)"); 1448bf215546Sopenharmony_ci return; 1449bf215546Sopenharmony_ci } 1450bf215546Sopenharmony_ci 1451bf215546Sopenharmony_ci /* No effect if vertex maps disabled. 1452bf215546Sopenharmony_ci */ 1453bf215546Sopenharmony_ci if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) 1454bf215546Sopenharmony_ci return; 1455bf215546Sopenharmony_ci 1456bf215546Sopenharmony_ci du = ctx->Eval.MapGrid2du; 1457bf215546Sopenharmony_ci dv = ctx->Eval.MapGrid2dv; 1458bf215546Sopenharmony_ci v1 = ctx->Eval.MapGrid2v1 + j1 * dv; 1459bf215546Sopenharmony_ci u1 = ctx->Eval.MapGrid2u1 + i1 * du; 1460bf215546Sopenharmony_ci 1461bf215546Sopenharmony_ci struct _glapi_table *dispatch; 1462bf215546Sopenharmony_ci 1463bf215546Sopenharmony_ci switch (mode) { 1464bf215546Sopenharmony_ci case GL_POINT: 1465bf215546Sopenharmony_ci CALL_Begin(ctx->CurrentServerDispatch, (GL_POINTS)); 1466bf215546Sopenharmony_ci /* Begin can change CurrentServerDispatch. */ 1467bf215546Sopenharmony_ci dispatch = ctx->CurrentServerDispatch; 1468bf215546Sopenharmony_ci for (v = v1, j = j1; j <= j2; j++, v += dv) { 1469bf215546Sopenharmony_ci for (u = u1, i = i1; i <= i2; i++, u += du) { 1470bf215546Sopenharmony_ci CALL_EvalCoord2f(dispatch, (u, v)); 1471bf215546Sopenharmony_ci } 1472bf215546Sopenharmony_ci } 1473bf215546Sopenharmony_ci CALL_End(dispatch, ()); 1474bf215546Sopenharmony_ci break; 1475bf215546Sopenharmony_ci case GL_LINE: 1476bf215546Sopenharmony_ci for (v = v1, j = j1; j <= j2; j++, v += dv) { 1477bf215546Sopenharmony_ci CALL_Begin(ctx->CurrentServerDispatch, (GL_LINE_STRIP)); 1478bf215546Sopenharmony_ci /* Begin can change CurrentServerDispatch. */ 1479bf215546Sopenharmony_ci dispatch = ctx->CurrentServerDispatch; 1480bf215546Sopenharmony_ci for (u = u1, i = i1; i <= i2; i++, u += du) { 1481bf215546Sopenharmony_ci CALL_EvalCoord2f(dispatch, (u, v)); 1482bf215546Sopenharmony_ci } 1483bf215546Sopenharmony_ci CALL_End(dispatch, ()); 1484bf215546Sopenharmony_ci } 1485bf215546Sopenharmony_ci for (u = u1, i = i1; i <= i2; i++, u += du) { 1486bf215546Sopenharmony_ci CALL_Begin(ctx->CurrentServerDispatch, (GL_LINE_STRIP)); 1487bf215546Sopenharmony_ci /* Begin can change CurrentServerDispatch. */ 1488bf215546Sopenharmony_ci dispatch = ctx->CurrentServerDispatch; 1489bf215546Sopenharmony_ci for (v = v1, j = j1; j <= j2; j++, v += dv) { 1490bf215546Sopenharmony_ci CALL_EvalCoord2f(dispatch, (u, v)); 1491bf215546Sopenharmony_ci } 1492bf215546Sopenharmony_ci CALL_End(dispatch, ()); 1493bf215546Sopenharmony_ci } 1494bf215546Sopenharmony_ci break; 1495bf215546Sopenharmony_ci case GL_FILL: 1496bf215546Sopenharmony_ci for (v = v1, j = j1; j < j2; j++, v += dv) { 1497bf215546Sopenharmony_ci CALL_Begin(ctx->CurrentServerDispatch, (GL_TRIANGLE_STRIP)); 1498bf215546Sopenharmony_ci /* Begin can change CurrentServerDispatch. */ 1499bf215546Sopenharmony_ci dispatch = ctx->CurrentServerDispatch; 1500bf215546Sopenharmony_ci for (u = u1, i = i1; i <= i2; i++, u += du) { 1501bf215546Sopenharmony_ci CALL_EvalCoord2f(dispatch, (u, v)); 1502bf215546Sopenharmony_ci CALL_EvalCoord2f(dispatch, (u, v + dv)); 1503bf215546Sopenharmony_ci } 1504bf215546Sopenharmony_ci CALL_End(dispatch, ()); 1505bf215546Sopenharmony_ci } 1506bf215546Sopenharmony_ci break; 1507bf215546Sopenharmony_ci } 1508bf215546Sopenharmony_ci} 1509bf215546Sopenharmony_ci 1510bf215546Sopenharmony_ci 1511bf215546Sopenharmony_ci/** 1512bf215546Sopenharmony_ci * Called from glDrawArrays when in immediate mode (not display list mode). 1513bf215546Sopenharmony_ci */ 1514bf215546Sopenharmony_civoid GLAPIENTRY 1515bf215546Sopenharmony_ci_mesa_DrawArrays(GLenum mode, GLint start, GLsizei count) 1516bf215546Sopenharmony_ci{ 1517bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1518bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1519bf215546Sopenharmony_ci 1520bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1521bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1522bf215546Sopenharmony_ci 1523bf215546Sopenharmony_ci if (ctx->NewState) 1524bf215546Sopenharmony_ci _mesa_update_state(ctx); 1525bf215546Sopenharmony_ci 1526bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1527bf215546Sopenharmony_ci !_mesa_validate_DrawArrays(ctx, mode, count)) 1528bf215546Sopenharmony_ci return; 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci if (0) 1531bf215546Sopenharmony_ci check_draw_arrays_data(ctx, start, count); 1532bf215546Sopenharmony_ci 1533bf215546Sopenharmony_ci _mesa_draw_arrays(ctx, mode, start, count, 1, 0); 1534bf215546Sopenharmony_ci 1535bf215546Sopenharmony_ci if (0) 1536bf215546Sopenharmony_ci print_draw_arrays(ctx, mode, start, count); 1537bf215546Sopenharmony_ci} 1538bf215546Sopenharmony_ci 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_ci/** 1541bf215546Sopenharmony_ci * Called from glDrawArraysInstanced when in immediate mode (not 1542bf215546Sopenharmony_ci * display list mode). 1543bf215546Sopenharmony_ci */ 1544bf215546Sopenharmony_civoid GLAPIENTRY 1545bf215546Sopenharmony_ci_mesa_DrawArraysInstancedARB(GLenum mode, GLint start, GLsizei count, 1546bf215546Sopenharmony_ci GLsizei numInstances) 1547bf215546Sopenharmony_ci{ 1548bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1549bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1550bf215546Sopenharmony_ci 1551bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1552bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci if (ctx->NewState) 1555bf215546Sopenharmony_ci _mesa_update_state(ctx); 1556bf215546Sopenharmony_ci 1557bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1558bf215546Sopenharmony_ci !_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, 1559bf215546Sopenharmony_ci numInstances)) 1560bf215546Sopenharmony_ci return; 1561bf215546Sopenharmony_ci 1562bf215546Sopenharmony_ci if (0) 1563bf215546Sopenharmony_ci check_draw_arrays_data(ctx, start, count); 1564bf215546Sopenharmony_ci 1565bf215546Sopenharmony_ci _mesa_draw_arrays(ctx, mode, start, count, numInstances, 0); 1566bf215546Sopenharmony_ci 1567bf215546Sopenharmony_ci if (0) 1568bf215546Sopenharmony_ci print_draw_arrays(ctx, mode, start, count); 1569bf215546Sopenharmony_ci} 1570bf215546Sopenharmony_ci 1571bf215546Sopenharmony_ci 1572bf215546Sopenharmony_ci/** 1573bf215546Sopenharmony_ci * Called from glDrawArraysInstancedBaseInstance when in immediate mode. 1574bf215546Sopenharmony_ci */ 1575bf215546Sopenharmony_civoid GLAPIENTRY 1576bf215546Sopenharmony_ci_mesa_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, 1577bf215546Sopenharmony_ci GLsizei count, GLsizei numInstances, 1578bf215546Sopenharmony_ci GLuint baseInstance) 1579bf215546Sopenharmony_ci{ 1580bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1581bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1582bf215546Sopenharmony_ci 1583bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1584bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1585bf215546Sopenharmony_ci 1586bf215546Sopenharmony_ci if (ctx->NewState) 1587bf215546Sopenharmony_ci _mesa_update_state(ctx); 1588bf215546Sopenharmony_ci 1589bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1590bf215546Sopenharmony_ci !_mesa_validate_DrawArraysInstanced(ctx, mode, first, count, 1591bf215546Sopenharmony_ci numInstances)) 1592bf215546Sopenharmony_ci return; 1593bf215546Sopenharmony_ci 1594bf215546Sopenharmony_ci if (0) 1595bf215546Sopenharmony_ci check_draw_arrays_data(ctx, first, count); 1596bf215546Sopenharmony_ci 1597bf215546Sopenharmony_ci _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance); 1598bf215546Sopenharmony_ci 1599bf215546Sopenharmony_ci if (0) 1600bf215546Sopenharmony_ci print_draw_arrays(ctx, mode, first, count); 1601bf215546Sopenharmony_ci} 1602bf215546Sopenharmony_ci 1603bf215546Sopenharmony_ci 1604bf215546Sopenharmony_ci/** 1605bf215546Sopenharmony_ci * Called from glMultiDrawArrays when in immediate mode. 1606bf215546Sopenharmony_ci */ 1607bf215546Sopenharmony_civoid GLAPIENTRY 1608bf215546Sopenharmony_ci_mesa_MultiDrawArrays(GLenum mode, const GLint *first, 1609bf215546Sopenharmony_ci const GLsizei *count, GLsizei primcount) 1610bf215546Sopenharmony_ci{ 1611bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1612bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1613bf215546Sopenharmony_ci 1614bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1615bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1616bf215546Sopenharmony_ci 1617bf215546Sopenharmony_ci if (ctx->NewState) 1618bf215546Sopenharmony_ci _mesa_update_state(ctx); 1619bf215546Sopenharmony_ci 1620bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1621bf215546Sopenharmony_ci !_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount)) 1622bf215546Sopenharmony_ci return; 1623bf215546Sopenharmony_ci 1624bf215546Sopenharmony_ci if (primcount == 0) 1625bf215546Sopenharmony_ci return; 1626bf215546Sopenharmony_ci 1627bf215546Sopenharmony_ci struct pipe_draw_info info; 1628bf215546Sopenharmony_ci struct pipe_draw_start_count_bias *draw; 1629bf215546Sopenharmony_ci 1630bf215546Sopenharmony_ci ALLOC_PRIMS(draw, primcount, "glMultiDrawElements"); 1631bf215546Sopenharmony_ci 1632bf215546Sopenharmony_ci info.mode = mode; 1633bf215546Sopenharmony_ci info.index_size = 0; 1634bf215546Sopenharmony_ci /* Packed section begin. */ 1635bf215546Sopenharmony_ci info.primitive_restart = false; 1636bf215546Sopenharmony_ci info.has_user_indices = false; 1637bf215546Sopenharmony_ci info.index_bounds_valid = false; 1638bf215546Sopenharmony_ci info.increment_draw_id = primcount > 1; 1639bf215546Sopenharmony_ci info.was_line_loop = false; 1640bf215546Sopenharmony_ci info.take_index_buffer_ownership = false; 1641bf215546Sopenharmony_ci info.index_bias_varies = false; 1642bf215546Sopenharmony_ci /* Packed section end. */ 1643bf215546Sopenharmony_ci info.start_instance = 0; 1644bf215546Sopenharmony_ci info.instance_count = 1; 1645bf215546Sopenharmony_ci info.view_mask = 0; 1646bf215546Sopenharmony_ci 1647bf215546Sopenharmony_ci for (int i = 0; i < primcount; i++) { 1648bf215546Sopenharmony_ci draw[i].start = first[i]; 1649bf215546Sopenharmony_ci draw[i].count = count[i]; 1650bf215546Sopenharmony_ci } 1651bf215546Sopenharmony_ci 1652bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, 0, draw, primcount); 1653bf215546Sopenharmony_ci 1654bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1655bf215546Sopenharmony_ci _mesa_flush(ctx); 1656bf215546Sopenharmony_ci 1657bf215546Sopenharmony_ci FREE_PRIMS(draw, primcount); 1658bf215546Sopenharmony_ci} 1659bf215546Sopenharmony_ci 1660bf215546Sopenharmony_ci 1661bf215546Sopenharmony_ci 1662bf215546Sopenharmony_ci/** 1663bf215546Sopenharmony_ci * Map GL_ELEMENT_ARRAY_BUFFER and print contents. 1664bf215546Sopenharmony_ci * For debugging. 1665bf215546Sopenharmony_ci */ 1666bf215546Sopenharmony_ci#if 0 1667bf215546Sopenharmony_cistatic void 1668bf215546Sopenharmony_cidump_element_buffer(struct gl_context *ctx, GLenum type) 1669bf215546Sopenharmony_ci{ 1670bf215546Sopenharmony_ci const GLvoid *map = 1671bf215546Sopenharmony_ci ctx->Driver.MapBufferRange(ctx, 0, 1672bf215546Sopenharmony_ci ctx->Array.VAO->IndexBufferObj->Size, 1673bf215546Sopenharmony_ci GL_MAP_READ_BIT, 1674bf215546Sopenharmony_ci ctx->Array.VAO->IndexBufferObj, 1675bf215546Sopenharmony_ci MAP_INTERNAL); 1676bf215546Sopenharmony_ci switch (type) { 1677bf215546Sopenharmony_ci case GL_UNSIGNED_BYTE: 1678bf215546Sopenharmony_ci { 1679bf215546Sopenharmony_ci const GLubyte *us = (const GLubyte *) map; 1680bf215546Sopenharmony_ci GLint i; 1681bf215546Sopenharmony_ci for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) { 1682bf215546Sopenharmony_ci printf("%02x ", us[i]); 1683bf215546Sopenharmony_ci if (i % 32 == 31) 1684bf215546Sopenharmony_ci printf("\n"); 1685bf215546Sopenharmony_ci } 1686bf215546Sopenharmony_ci printf("\n"); 1687bf215546Sopenharmony_ci } 1688bf215546Sopenharmony_ci break; 1689bf215546Sopenharmony_ci case GL_UNSIGNED_SHORT: 1690bf215546Sopenharmony_ci { 1691bf215546Sopenharmony_ci const GLushort *us = (const GLushort *) map; 1692bf215546Sopenharmony_ci GLint i; 1693bf215546Sopenharmony_ci for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) { 1694bf215546Sopenharmony_ci printf("%04x ", us[i]); 1695bf215546Sopenharmony_ci if (i % 16 == 15) 1696bf215546Sopenharmony_ci printf("\n"); 1697bf215546Sopenharmony_ci } 1698bf215546Sopenharmony_ci printf("\n"); 1699bf215546Sopenharmony_ci } 1700bf215546Sopenharmony_ci break; 1701bf215546Sopenharmony_ci case GL_UNSIGNED_INT: 1702bf215546Sopenharmony_ci { 1703bf215546Sopenharmony_ci const GLuint *us = (const GLuint *) map; 1704bf215546Sopenharmony_ci GLint i; 1705bf215546Sopenharmony_ci for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) { 1706bf215546Sopenharmony_ci printf("%08x ", us[i]); 1707bf215546Sopenharmony_ci if (i % 8 == 7) 1708bf215546Sopenharmony_ci printf("\n"); 1709bf215546Sopenharmony_ci } 1710bf215546Sopenharmony_ci printf("\n"); 1711bf215546Sopenharmony_ci } 1712bf215546Sopenharmony_ci break; 1713bf215546Sopenharmony_ci default: 1714bf215546Sopenharmony_ci ; 1715bf215546Sopenharmony_ci } 1716bf215546Sopenharmony_ci 1717bf215546Sopenharmony_ci ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL); 1718bf215546Sopenharmony_ci} 1719bf215546Sopenharmony_ci#endif 1720bf215546Sopenharmony_ci 1721bf215546Sopenharmony_ci 1722bf215546Sopenharmony_ci/** 1723bf215546Sopenharmony_ci * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements. 1724bf215546Sopenharmony_ci * Do the rendering for a glDrawElements or glDrawRangeElements call after 1725bf215546Sopenharmony_ci * we've validated buffer bounds, etc. 1726bf215546Sopenharmony_ci */ 1727bf215546Sopenharmony_cistatic void 1728bf215546Sopenharmony_ci_mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, 1729bf215546Sopenharmony_ci bool index_bounds_valid, 1730bf215546Sopenharmony_ci GLuint start, GLuint end, 1731bf215546Sopenharmony_ci GLsizei count, GLenum type, 1732bf215546Sopenharmony_ci const GLvoid * indices, 1733bf215546Sopenharmony_ci GLint basevertex, GLuint numInstances, 1734bf215546Sopenharmony_ci GLuint baseInstance) 1735bf215546Sopenharmony_ci{ 1736bf215546Sopenharmony_ci /* Viewperf has many draws with count=0. Discarding them is faster than 1737bf215546Sopenharmony_ci * processing them. 1738bf215546Sopenharmony_ci */ 1739bf215546Sopenharmony_ci if (!count || !numInstances) 1740bf215546Sopenharmony_ci return; 1741bf215546Sopenharmony_ci 1742bf215546Sopenharmony_ci if (!index_bounds_valid) { 1743bf215546Sopenharmony_ci assert(start == 0u); 1744bf215546Sopenharmony_ci assert(end == ~0u); 1745bf215546Sopenharmony_ci } 1746bf215546Sopenharmony_ci 1747bf215546Sopenharmony_ci struct pipe_draw_info info; 1748bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 1749bf215546Sopenharmony_ci unsigned index_size_shift = get_index_size_shift(type); 1750bf215546Sopenharmony_ci struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj; 1751bf215546Sopenharmony_ci 1752bf215546Sopenharmony_ci if (index_bo && !indices_aligned(index_size_shift, indices)) 1753bf215546Sopenharmony_ci return; 1754bf215546Sopenharmony_ci 1755bf215546Sopenharmony_ci info.mode = mode; 1756bf215546Sopenharmony_ci info.index_size = 1 << index_size_shift; 1757bf215546Sopenharmony_ci /* Packed section begin. */ 1758bf215546Sopenharmony_ci info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift]; 1759bf215546Sopenharmony_ci info.has_user_indices = index_bo == NULL; 1760bf215546Sopenharmony_ci info.index_bounds_valid = index_bounds_valid; 1761bf215546Sopenharmony_ci info.increment_draw_id = false; 1762bf215546Sopenharmony_ci info.was_line_loop = false; 1763bf215546Sopenharmony_ci info.take_index_buffer_ownership = false; 1764bf215546Sopenharmony_ci info.index_bias_varies = false; 1765bf215546Sopenharmony_ci /* Packed section end. */ 1766bf215546Sopenharmony_ci info.start_instance = baseInstance; 1767bf215546Sopenharmony_ci info.instance_count = numInstances; 1768bf215546Sopenharmony_ci info.view_mask = 0; 1769bf215546Sopenharmony_ci info.restart_index = ctx->Array._RestartIndex[index_size_shift]; 1770bf215546Sopenharmony_ci 1771bf215546Sopenharmony_ci if (info.has_user_indices) { 1772bf215546Sopenharmony_ci info.index.user = indices; 1773bf215546Sopenharmony_ci draw.start = 0; 1774bf215546Sopenharmony_ci } else { 1775bf215546Sopenharmony_ci uintptr_t start = (uintptr_t) indices; 1776bf215546Sopenharmony_ci if (unlikely(index_bo->Size < start)) { 1777bf215546Sopenharmony_ci _mesa_warning(ctx, "Invalid indices offset 0x%" PRIxPTR 1778bf215546Sopenharmony_ci " (indices buffer size is %ld bytes)." 1779bf215546Sopenharmony_ci " Draw skipped.", start, index_bo->Size); 1780bf215546Sopenharmony_ci return; 1781bf215546Sopenharmony_ci } 1782bf215546Sopenharmony_ci info.index.gl_bo = index_bo; 1783bf215546Sopenharmony_ci draw.start = start >> index_size_shift; 1784bf215546Sopenharmony_ci } 1785bf215546Sopenharmony_ci draw.index_bias = basevertex; 1786bf215546Sopenharmony_ci 1787bf215546Sopenharmony_ci info.min_index = start; 1788bf215546Sopenharmony_ci info.max_index = end; 1789bf215546Sopenharmony_ci draw.count = count; 1790bf215546Sopenharmony_ci 1791bf215546Sopenharmony_ci /* Need to give special consideration to rendering a range of 1792bf215546Sopenharmony_ci * indices starting somewhere above zero. Typically the 1793bf215546Sopenharmony_ci * application is issuing multiple DrawRangeElements() to draw 1794bf215546Sopenharmony_ci * successive primitives layed out linearly in the vertex arrays. 1795bf215546Sopenharmony_ci * Unless the vertex arrays are all in a VBO (or locked as with 1796bf215546Sopenharmony_ci * CVA), the OpenGL semantics imply that we need to re-read or 1797bf215546Sopenharmony_ci * re-upload the vertex data on each draw call. 1798bf215546Sopenharmony_ci * 1799bf215546Sopenharmony_ci * In the case of hardware tnl, we want to avoid starting the 1800bf215546Sopenharmony_ci * upload at zero, as it will mean every draw call uploads an 1801bf215546Sopenharmony_ci * increasing amount of not-used vertex data. Worse - in the 1802bf215546Sopenharmony_ci * software tnl module, all those vertices might be transformed and 1803bf215546Sopenharmony_ci * lit but never rendered. 1804bf215546Sopenharmony_ci * 1805bf215546Sopenharmony_ci * If we just upload or transform the vertices in start..end, 1806bf215546Sopenharmony_ci * however, the indices will be incorrect. 1807bf215546Sopenharmony_ci * 1808bf215546Sopenharmony_ci * At this level, we don't know exactly what the requirements of 1809bf215546Sopenharmony_ci * the backend are going to be, though it will likely boil down to 1810bf215546Sopenharmony_ci * either: 1811bf215546Sopenharmony_ci * 1812bf215546Sopenharmony_ci * 1) Do nothing, everything is in a VBO and is processed once 1813bf215546Sopenharmony_ci * only. 1814bf215546Sopenharmony_ci * 1815bf215546Sopenharmony_ci * 2) Adjust the indices and vertex arrays so that start becomes 1816bf215546Sopenharmony_ci * zero. 1817bf215546Sopenharmony_ci * 1818bf215546Sopenharmony_ci * Rather than doing anything here, I'll provide a helper function 1819bf215546Sopenharmony_ci * for the latter case elsewhere. 1820bf215546Sopenharmony_ci */ 1821bf215546Sopenharmony_ci 1822bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, 0, &draw, 1); 1823bf215546Sopenharmony_ci 1824bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 1825bf215546Sopenharmony_ci _mesa_flush(ctx); 1826bf215546Sopenharmony_ci } 1827bf215546Sopenharmony_ci} 1828bf215546Sopenharmony_ci 1829bf215546Sopenharmony_ci 1830bf215546Sopenharmony_ci/** 1831bf215546Sopenharmony_ci * Called by glDrawRangeElementsBaseVertex() in immediate mode. 1832bf215546Sopenharmony_ci */ 1833bf215546Sopenharmony_civoid GLAPIENTRY 1834bf215546Sopenharmony_ci_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, 1835bf215546Sopenharmony_ci GLsizei count, GLenum type, 1836bf215546Sopenharmony_ci const GLvoid * indices, GLint basevertex) 1837bf215546Sopenharmony_ci{ 1838bf215546Sopenharmony_ci static GLuint warnCount = 0; 1839bf215546Sopenharmony_ci bool index_bounds_valid = true; 1840bf215546Sopenharmony_ci 1841bf215546Sopenharmony_ci /* This is only useful to catch invalid values in the "end" parameter 1842bf215546Sopenharmony_ci * like ~0. 1843bf215546Sopenharmony_ci */ 1844bf215546Sopenharmony_ci GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */ 1845bf215546Sopenharmony_ci 1846bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1847bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1848bf215546Sopenharmony_ci 1849bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1850bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1851bf215546Sopenharmony_ci 1852bf215546Sopenharmony_ci if (ctx->NewState) 1853bf215546Sopenharmony_ci _mesa_update_state(ctx); 1854bf215546Sopenharmony_ci 1855bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1856bf215546Sopenharmony_ci !_mesa_validate_DrawRangeElements(ctx, mode, start, end, count, 1857bf215546Sopenharmony_ci type)) 1858bf215546Sopenharmony_ci return; 1859bf215546Sopenharmony_ci 1860bf215546Sopenharmony_ci if ((int) end + basevertex < 0 || start + basevertex >= max_element) { 1861bf215546Sopenharmony_ci /* The application requested we draw using a range of indices that's 1862bf215546Sopenharmony_ci * outside the bounds of the current VBO. This is invalid and appears 1863bf215546Sopenharmony_ci * to give undefined results. The safest thing to do is to simply 1864bf215546Sopenharmony_ci * ignore the range, in case the application botched their range tracking 1865bf215546Sopenharmony_ci * but did provide valid indices. Also issue a warning indicating that 1866bf215546Sopenharmony_ci * the application is broken. 1867bf215546Sopenharmony_ci */ 1868bf215546Sopenharmony_ci if (warnCount++ < 10) { 1869bf215546Sopenharmony_ci _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, " 1870bf215546Sopenharmony_ci "basevertex %d, count %d, type 0x%x, indices=%p):\n" 1871bf215546Sopenharmony_ci "\trange is outside VBO bounds (max=%u); ignoring.\n" 1872bf215546Sopenharmony_ci "\tThis should be fixed in the application.", 1873bf215546Sopenharmony_ci start, end, basevertex, count, type, indices, 1874bf215546Sopenharmony_ci max_element - 1); 1875bf215546Sopenharmony_ci } 1876bf215546Sopenharmony_ci index_bounds_valid = false; 1877bf215546Sopenharmony_ci } 1878bf215546Sopenharmony_ci 1879bf215546Sopenharmony_ci /* NOTE: It's important that 'end' is a reasonable value. 1880bf215546Sopenharmony_ci * in _tnl_draw_prims(), we use end to determine how many vertices 1881bf215546Sopenharmony_ci * to transform. If it's too large, we can unnecessarily split prims 1882bf215546Sopenharmony_ci * or we can read/write out of memory in several different places! 1883bf215546Sopenharmony_ci */ 1884bf215546Sopenharmony_ci 1885bf215546Sopenharmony_ci /* Catch/fix some potential user errors */ 1886bf215546Sopenharmony_ci if (type == GL_UNSIGNED_BYTE) { 1887bf215546Sopenharmony_ci start = MIN2(start, 0xff); 1888bf215546Sopenharmony_ci end = MIN2(end, 0xff); 1889bf215546Sopenharmony_ci } 1890bf215546Sopenharmony_ci else if (type == GL_UNSIGNED_SHORT) { 1891bf215546Sopenharmony_ci start = MIN2(start, 0xffff); 1892bf215546Sopenharmony_ci end = MIN2(end, 0xffff); 1893bf215546Sopenharmony_ci } 1894bf215546Sopenharmony_ci 1895bf215546Sopenharmony_ci if (0) { 1896bf215546Sopenharmony_ci printf("glDraw[Range]Elements{,BaseVertex}" 1897bf215546Sopenharmony_ci "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, " 1898bf215546Sopenharmony_ci "base %d\n", 1899bf215546Sopenharmony_ci start, end, type, count, 1900bf215546Sopenharmony_ci ctx->Array.VAO->IndexBufferObj ? 1901bf215546Sopenharmony_ci ctx->Array.VAO->IndexBufferObj->Name : 0, basevertex); 1902bf215546Sopenharmony_ci } 1903bf215546Sopenharmony_ci 1904bf215546Sopenharmony_ci if ((int) start + basevertex < 0 || end + basevertex >= max_element) 1905bf215546Sopenharmony_ci index_bounds_valid = false; 1906bf215546Sopenharmony_ci 1907bf215546Sopenharmony_ci#if 0 1908bf215546Sopenharmony_ci check_draw_elements_data(ctx, count, type, indices, basevertex); 1909bf215546Sopenharmony_ci#else 1910bf215546Sopenharmony_ci (void) check_draw_elements_data; 1911bf215546Sopenharmony_ci#endif 1912bf215546Sopenharmony_ci 1913bf215546Sopenharmony_ci if (!index_bounds_valid) { 1914bf215546Sopenharmony_ci start = 0; 1915bf215546Sopenharmony_ci end = ~0; 1916bf215546Sopenharmony_ci } 1917bf215546Sopenharmony_ci 1918bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end, 1919bf215546Sopenharmony_ci count, type, indices, basevertex, 1, 0); 1920bf215546Sopenharmony_ci} 1921bf215546Sopenharmony_ci 1922bf215546Sopenharmony_ci 1923bf215546Sopenharmony_ci/** 1924bf215546Sopenharmony_ci * Called by glDrawRangeElements() in immediate mode. 1925bf215546Sopenharmony_ci */ 1926bf215546Sopenharmony_civoid GLAPIENTRY 1927bf215546Sopenharmony_ci_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, 1928bf215546Sopenharmony_ci GLsizei count, GLenum type, const GLvoid * indices) 1929bf215546Sopenharmony_ci{ 1930bf215546Sopenharmony_ci _mesa_DrawRangeElementsBaseVertex(mode, start, end, count, type, 1931bf215546Sopenharmony_ci indices, 0); 1932bf215546Sopenharmony_ci} 1933bf215546Sopenharmony_ci 1934bf215546Sopenharmony_ci 1935bf215546Sopenharmony_ci/** 1936bf215546Sopenharmony_ci * Called by glDrawElements() in immediate mode. 1937bf215546Sopenharmony_ci */ 1938bf215546Sopenharmony_civoid GLAPIENTRY 1939bf215546Sopenharmony_ci_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, 1940bf215546Sopenharmony_ci const GLvoid * indices) 1941bf215546Sopenharmony_ci{ 1942bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1943bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1944bf215546Sopenharmony_ci 1945bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1946bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1947bf215546Sopenharmony_ci 1948bf215546Sopenharmony_ci if (ctx->NewState) 1949bf215546Sopenharmony_ci _mesa_update_state(ctx); 1950bf215546Sopenharmony_ci 1951bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1952bf215546Sopenharmony_ci !_mesa_validate_DrawElements(ctx, mode, count, type)) 1953bf215546Sopenharmony_ci return; 1954bf215546Sopenharmony_ci 1955bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0, 1956bf215546Sopenharmony_ci count, type, indices, 0, 1, 0); 1957bf215546Sopenharmony_ci} 1958bf215546Sopenharmony_ci 1959bf215546Sopenharmony_ci 1960bf215546Sopenharmony_ci/** 1961bf215546Sopenharmony_ci * Called by glDrawElementsBaseVertex() in immediate mode. 1962bf215546Sopenharmony_ci */ 1963bf215546Sopenharmony_civoid GLAPIENTRY 1964bf215546Sopenharmony_ci_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 1965bf215546Sopenharmony_ci const GLvoid * indices, GLint basevertex) 1966bf215546Sopenharmony_ci{ 1967bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1968bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1969bf215546Sopenharmony_ci 1970bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1971bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1972bf215546Sopenharmony_ci 1973bf215546Sopenharmony_ci if (ctx->NewState) 1974bf215546Sopenharmony_ci _mesa_update_state(ctx); 1975bf215546Sopenharmony_ci 1976bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 1977bf215546Sopenharmony_ci !_mesa_validate_DrawElements(ctx, mode, count, type)) 1978bf215546Sopenharmony_ci return; 1979bf215546Sopenharmony_ci 1980bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0, 1981bf215546Sopenharmony_ci count, type, indices, basevertex, 1, 0); 1982bf215546Sopenharmony_ci} 1983bf215546Sopenharmony_ci 1984bf215546Sopenharmony_ci 1985bf215546Sopenharmony_ci/** 1986bf215546Sopenharmony_ci * Called by glDrawElementsInstanced() in immediate mode. 1987bf215546Sopenharmony_ci */ 1988bf215546Sopenharmony_civoid GLAPIENTRY 1989bf215546Sopenharmony_ci_mesa_DrawElementsInstancedARB(GLenum mode, GLsizei count, GLenum type, 1990bf215546Sopenharmony_ci const GLvoid * indices, GLsizei numInstances) 1991bf215546Sopenharmony_ci{ 1992bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1993bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 1994bf215546Sopenharmony_ci 1995bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 1996bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 1997bf215546Sopenharmony_ci 1998bf215546Sopenharmony_ci if (ctx->NewState) 1999bf215546Sopenharmony_ci _mesa_update_state(ctx); 2000bf215546Sopenharmony_ci 2001bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2002bf215546Sopenharmony_ci !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 2003bf215546Sopenharmony_ci numInstances)) 2004bf215546Sopenharmony_ci return; 2005bf215546Sopenharmony_ci 2006bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0, 2007bf215546Sopenharmony_ci count, type, indices, 0, numInstances, 0); 2008bf215546Sopenharmony_ci} 2009bf215546Sopenharmony_ci 2010bf215546Sopenharmony_ci 2011bf215546Sopenharmony_ci/** 2012bf215546Sopenharmony_ci * Called by glDrawElementsInstancedBaseVertex() in immediate mode. 2013bf215546Sopenharmony_ci */ 2014bf215546Sopenharmony_civoid GLAPIENTRY 2015bf215546Sopenharmony_ci_mesa_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, 2016bf215546Sopenharmony_ci GLenum type, const GLvoid * indices, 2017bf215546Sopenharmony_ci GLsizei numInstances, 2018bf215546Sopenharmony_ci GLint basevertex) 2019bf215546Sopenharmony_ci{ 2020bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2021bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2022bf215546Sopenharmony_ci 2023bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2024bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2025bf215546Sopenharmony_ci 2026bf215546Sopenharmony_ci if (ctx->NewState) 2027bf215546Sopenharmony_ci _mesa_update_state(ctx); 2028bf215546Sopenharmony_ci 2029bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2030bf215546Sopenharmony_ci !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 2031bf215546Sopenharmony_ci numInstances)) 2032bf215546Sopenharmony_ci return; 2033bf215546Sopenharmony_ci 2034bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0, 2035bf215546Sopenharmony_ci count, type, indices, 2036bf215546Sopenharmony_ci basevertex, numInstances, 0); 2037bf215546Sopenharmony_ci} 2038bf215546Sopenharmony_ci 2039bf215546Sopenharmony_ci 2040bf215546Sopenharmony_ci/** 2041bf215546Sopenharmony_ci * Called by glDrawElementsInstancedBaseInstance() in immediate mode. 2042bf215546Sopenharmony_ci */ 2043bf215546Sopenharmony_civoid GLAPIENTRY 2044bf215546Sopenharmony_ci_mesa_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, 2045bf215546Sopenharmony_ci GLenum type, 2046bf215546Sopenharmony_ci const GLvoid *indices, 2047bf215546Sopenharmony_ci GLsizei numInstances, 2048bf215546Sopenharmony_ci GLuint baseInstance) 2049bf215546Sopenharmony_ci{ 2050bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2051bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2052bf215546Sopenharmony_ci 2053bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2054bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2055bf215546Sopenharmony_ci 2056bf215546Sopenharmony_ci if (ctx->NewState) 2057bf215546Sopenharmony_ci _mesa_update_state(ctx); 2058bf215546Sopenharmony_ci 2059bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2060bf215546Sopenharmony_ci !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 2061bf215546Sopenharmony_ci numInstances)) 2062bf215546Sopenharmony_ci return; 2063bf215546Sopenharmony_ci 2064bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0, 2065bf215546Sopenharmony_ci count, type, indices, 0, numInstances, 2066bf215546Sopenharmony_ci baseInstance); 2067bf215546Sopenharmony_ci} 2068bf215546Sopenharmony_ci 2069bf215546Sopenharmony_ci 2070bf215546Sopenharmony_ci/** 2071bf215546Sopenharmony_ci * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode. 2072bf215546Sopenharmony_ci */ 2073bf215546Sopenharmony_civoid GLAPIENTRY 2074bf215546Sopenharmony_ci_mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, 2075bf215546Sopenharmony_ci GLsizei count, 2076bf215546Sopenharmony_ci GLenum type, 2077bf215546Sopenharmony_ci const GLvoid *indices, 2078bf215546Sopenharmony_ci GLsizei numInstances, 2079bf215546Sopenharmony_ci GLint basevertex, 2080bf215546Sopenharmony_ci GLuint baseInstance) 2081bf215546Sopenharmony_ci{ 2082bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2083bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2084bf215546Sopenharmony_ci 2085bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2086bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2087bf215546Sopenharmony_ci 2088bf215546Sopenharmony_ci if (ctx->NewState) 2089bf215546Sopenharmony_ci _mesa_update_state(ctx); 2090bf215546Sopenharmony_ci 2091bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2092bf215546Sopenharmony_ci !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 2093bf215546Sopenharmony_ci numInstances)) 2094bf215546Sopenharmony_ci return; 2095bf215546Sopenharmony_ci 2096bf215546Sopenharmony_ci _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0, 2097bf215546Sopenharmony_ci count, type, indices, basevertex, 2098bf215546Sopenharmony_ci numInstances, baseInstance); 2099bf215546Sopenharmony_ci} 2100bf215546Sopenharmony_ci 2101bf215546Sopenharmony_ci 2102bf215546Sopenharmony_ci/** 2103bf215546Sopenharmony_ci * Inner support for both _mesa_MultiDrawElements() and 2104bf215546Sopenharmony_ci * _mesa_MultiDrawRangeElements(). 2105bf215546Sopenharmony_ci * This does the actual rendering after we've checked array indexes, etc. 2106bf215546Sopenharmony_ci */ 2107bf215546Sopenharmony_cistatic void 2108bf215546Sopenharmony_ci_mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode, 2109bf215546Sopenharmony_ci const GLsizei *count, GLenum type, 2110bf215546Sopenharmony_ci const GLvoid * const *indices, 2111bf215546Sopenharmony_ci GLsizei primcount, const GLint *basevertex) 2112bf215546Sopenharmony_ci{ 2113bf215546Sopenharmony_ci uintptr_t min_index_ptr, max_index_ptr; 2114bf215546Sopenharmony_ci bool fallback = false; 2115bf215546Sopenharmony_ci int i; 2116bf215546Sopenharmony_ci 2117bf215546Sopenharmony_ci if (primcount == 0) 2118bf215546Sopenharmony_ci return; 2119bf215546Sopenharmony_ci 2120bf215546Sopenharmony_ci unsigned index_size_shift = get_index_size_shift(type); 2121bf215546Sopenharmony_ci 2122bf215546Sopenharmony_ci min_index_ptr = (uintptr_t) indices[0]; 2123bf215546Sopenharmony_ci max_index_ptr = 0; 2124bf215546Sopenharmony_ci for (i = 0; i < primcount; i++) { 2125bf215546Sopenharmony_ci min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]); 2126bf215546Sopenharmony_ci max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] + 2127bf215546Sopenharmony_ci (count[i] << index_size_shift)); 2128bf215546Sopenharmony_ci } 2129bf215546Sopenharmony_ci 2130bf215546Sopenharmony_ci /* Check if we can handle this thing as a bunch of index offsets from the 2131bf215546Sopenharmony_ci * same index pointer. If we can't, then we have to fall back to doing 2132bf215546Sopenharmony_ci * a draw_prims per primitive. 2133bf215546Sopenharmony_ci * Check that the difference between each prim's indexes is a multiple of 2134bf215546Sopenharmony_ci * the index/element size. 2135bf215546Sopenharmony_ci */ 2136bf215546Sopenharmony_ci if (index_size_shift) { 2137bf215546Sopenharmony_ci for (i = 0; i < primcount; i++) { 2138bf215546Sopenharmony_ci if ((((uintptr_t) indices[i] - min_index_ptr) & 2139bf215546Sopenharmony_ci ((1 << index_size_shift) - 1)) != 0) { 2140bf215546Sopenharmony_ci fallback = true; 2141bf215546Sopenharmony_ci break; 2142bf215546Sopenharmony_ci } 2143bf215546Sopenharmony_ci } 2144bf215546Sopenharmony_ci } 2145bf215546Sopenharmony_ci 2146bf215546Sopenharmony_ci struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj; 2147bf215546Sopenharmony_ci struct pipe_draw_info info; 2148bf215546Sopenharmony_ci 2149bf215546Sopenharmony_ci info.mode = mode; 2150bf215546Sopenharmony_ci info.index_size = 1 << index_size_shift; 2151bf215546Sopenharmony_ci /* Packed section begin. */ 2152bf215546Sopenharmony_ci info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift]; 2153bf215546Sopenharmony_ci info.has_user_indices = index_bo == NULL; 2154bf215546Sopenharmony_ci info.index_bounds_valid = false; 2155bf215546Sopenharmony_ci info.increment_draw_id = primcount > 1; 2156bf215546Sopenharmony_ci info.was_line_loop = false; 2157bf215546Sopenharmony_ci info.take_index_buffer_ownership = false; 2158bf215546Sopenharmony_ci info.index_bias_varies = !!basevertex; 2159bf215546Sopenharmony_ci /* Packed section end. */ 2160bf215546Sopenharmony_ci info.start_instance = 0; 2161bf215546Sopenharmony_ci info.instance_count = 1; 2162bf215546Sopenharmony_ci info.view_mask = 0; 2163bf215546Sopenharmony_ci info.restart_index = ctx->Array._RestartIndex[index_size_shift]; 2164bf215546Sopenharmony_ci 2165bf215546Sopenharmony_ci if (info.has_user_indices) 2166bf215546Sopenharmony_ci info.index.user = (void*)min_index_ptr; 2167bf215546Sopenharmony_ci else 2168bf215546Sopenharmony_ci info.index.gl_bo = index_bo; 2169bf215546Sopenharmony_ci 2170bf215546Sopenharmony_ci if (!fallback && 2171bf215546Sopenharmony_ci (!info.has_user_indices || 2172bf215546Sopenharmony_ci /* "max_index_ptr - min_index_ptr >> index_size_shift" is stored 2173bf215546Sopenharmony_ci * in draw[i].start. The driver will multiply it later by index_size 2174bf215546Sopenharmony_ci * so make sure the final value won't overflow. 2175bf215546Sopenharmony_ci * 2176bf215546Sopenharmony_ci * For real index buffers, gallium doesn't support index buffer offsets 2177bf215546Sopenharmony_ci * greater than UINT32_MAX bytes. 2178bf215546Sopenharmony_ci */ 2179bf215546Sopenharmony_ci max_index_ptr - min_index_ptr <= UINT32_MAX)) { 2180bf215546Sopenharmony_ci struct pipe_draw_start_count_bias *draw; 2181bf215546Sopenharmony_ci 2182bf215546Sopenharmony_ci ALLOC_PRIMS(draw, primcount, "glMultiDrawElements"); 2183bf215546Sopenharmony_ci 2184bf215546Sopenharmony_ci if (info.has_user_indices) { 2185bf215546Sopenharmony_ci for (int i = 0; i < primcount; i++) { 2186bf215546Sopenharmony_ci draw[i].start = 2187bf215546Sopenharmony_ci ((uintptr_t)indices[i] - min_index_ptr) >> index_size_shift; 2188bf215546Sopenharmony_ci draw[i].count = count[i]; 2189bf215546Sopenharmony_ci draw[i].index_bias = basevertex ? basevertex[i] : 0; 2190bf215546Sopenharmony_ci } 2191bf215546Sopenharmony_ci } else { 2192bf215546Sopenharmony_ci for (int i = 0; i < primcount; i++) { 2193bf215546Sopenharmony_ci draw[i].start = (uintptr_t)indices[i] >> index_size_shift; 2194bf215546Sopenharmony_ci draw[i].count = 2195bf215546Sopenharmony_ci indices_aligned(index_size_shift, indices[i]) ? count[i] : 0; 2196bf215546Sopenharmony_ci draw[i].index_bias = basevertex ? basevertex[i] : 0; 2197bf215546Sopenharmony_ci } 2198bf215546Sopenharmony_ci } 2199bf215546Sopenharmony_ci 2200bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, 0, draw, primcount); 2201bf215546Sopenharmony_ci FREE_PRIMS(draw, primcount); 2202bf215546Sopenharmony_ci } else { 2203bf215546Sopenharmony_ci /* draw[i].start would overflow. Draw one at a time. */ 2204bf215546Sopenharmony_ci assert(info.has_user_indices); 2205bf215546Sopenharmony_ci info.increment_draw_id = false; 2206bf215546Sopenharmony_ci 2207bf215546Sopenharmony_ci for (int i = 0; i < primcount; i++) { 2208bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 2209bf215546Sopenharmony_ci 2210bf215546Sopenharmony_ci if (!count[i]) 2211bf215546Sopenharmony_ci continue; 2212bf215546Sopenharmony_ci 2213bf215546Sopenharmony_ci /* Reset these, because the callee can change them. */ 2214bf215546Sopenharmony_ci info.index_bounds_valid = false; 2215bf215546Sopenharmony_ci info.index.user = indices[i]; 2216bf215546Sopenharmony_ci draw.start = 0; 2217bf215546Sopenharmony_ci draw.index_bias = basevertex ? basevertex[i] : 0; 2218bf215546Sopenharmony_ci draw.count = count[i]; 2219bf215546Sopenharmony_ci 2220bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1); 2221bf215546Sopenharmony_ci } 2222bf215546Sopenharmony_ci } 2223bf215546Sopenharmony_ci 2224bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 2225bf215546Sopenharmony_ci _mesa_flush(ctx); 2226bf215546Sopenharmony_ci } 2227bf215546Sopenharmony_ci} 2228bf215546Sopenharmony_ci 2229bf215546Sopenharmony_ci 2230bf215546Sopenharmony_civoid GLAPIENTRY 2231bf215546Sopenharmony_ci_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, 2232bf215546Sopenharmony_ci const GLvoid * const *indices, GLsizei primcount) 2233bf215546Sopenharmony_ci{ 2234bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2235bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2236bf215546Sopenharmony_ci 2237bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2238bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2239bf215546Sopenharmony_ci 2240bf215546Sopenharmony_ci if (ctx->NewState) 2241bf215546Sopenharmony_ci _mesa_update_state(ctx); 2242bf215546Sopenharmony_ci 2243bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2244bf215546Sopenharmony_ci !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, 2245bf215546Sopenharmony_ci primcount)) 2246bf215546Sopenharmony_ci return; 2247bf215546Sopenharmony_ci 2248bf215546Sopenharmony_ci _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 2249bf215546Sopenharmony_ci NULL); 2250bf215546Sopenharmony_ci} 2251bf215546Sopenharmony_ci 2252bf215546Sopenharmony_ci 2253bf215546Sopenharmony_civoid GLAPIENTRY 2254bf215546Sopenharmony_ci_mesa_MultiDrawElementsBaseVertex(GLenum mode, 2255bf215546Sopenharmony_ci const GLsizei *count, GLenum type, 2256bf215546Sopenharmony_ci const GLvoid * const *indices, 2257bf215546Sopenharmony_ci GLsizei primcount, 2258bf215546Sopenharmony_ci const GLsizei *basevertex) 2259bf215546Sopenharmony_ci{ 2260bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2261bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2262bf215546Sopenharmony_ci 2263bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2264bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2265bf215546Sopenharmony_ci 2266bf215546Sopenharmony_ci if (ctx->NewState) 2267bf215546Sopenharmony_ci _mesa_update_state(ctx); 2268bf215546Sopenharmony_ci 2269bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2270bf215546Sopenharmony_ci !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, 2271bf215546Sopenharmony_ci primcount)) 2272bf215546Sopenharmony_ci return; 2273bf215546Sopenharmony_ci 2274bf215546Sopenharmony_ci _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 2275bf215546Sopenharmony_ci basevertex); 2276bf215546Sopenharmony_ci} 2277bf215546Sopenharmony_ci 2278bf215546Sopenharmony_ci 2279bf215546Sopenharmony_ci/** 2280bf215546Sopenharmony_ci * Draw a GL primitive using a vertex count obtained from transform feedback. 2281bf215546Sopenharmony_ci * \param mode the type of GL primitive to draw 2282bf215546Sopenharmony_ci * \param obj the transform feedback object to use 2283bf215546Sopenharmony_ci * \param stream index of the transform feedback stream from which to 2284bf215546Sopenharmony_ci * get the primitive count. 2285bf215546Sopenharmony_ci * \param numInstances number of instances to draw 2286bf215546Sopenharmony_ci */ 2287bf215546Sopenharmony_cistatic void 2288bf215546Sopenharmony_ci_mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode, 2289bf215546Sopenharmony_ci struct gl_transform_feedback_object *obj, 2290bf215546Sopenharmony_ci GLuint stream, GLuint numInstances) 2291bf215546Sopenharmony_ci{ 2292bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2293bf215546Sopenharmony_ci 2294bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2295bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2296bf215546Sopenharmony_ci 2297bf215546Sopenharmony_ci if (ctx->NewState) 2298bf215546Sopenharmony_ci _mesa_update_state(ctx); 2299bf215546Sopenharmony_ci 2300bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2301bf215546Sopenharmony_ci !_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream, 2302bf215546Sopenharmony_ci numInstances)) 2303bf215546Sopenharmony_ci return; 2304bf215546Sopenharmony_ci 2305bf215546Sopenharmony_ci /* Maybe we should do some primitive splitting for primitive restart 2306bf215546Sopenharmony_ci * (like in DrawArrays), but we have no way to know how many vertices 2307bf215546Sopenharmony_ci * will be rendered. */ 2308bf215546Sopenharmony_ci 2309bf215546Sopenharmony_ci st_draw_transform_feedback(ctx, mode, numInstances, stream, obj); 2310bf215546Sopenharmony_ci 2311bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 2312bf215546Sopenharmony_ci _mesa_flush(ctx); 2313bf215546Sopenharmony_ci } 2314bf215546Sopenharmony_ci} 2315bf215546Sopenharmony_ci 2316bf215546Sopenharmony_ci 2317bf215546Sopenharmony_ci/** 2318bf215546Sopenharmony_ci * Like DrawArrays, but take the count from a transform feedback object. 2319bf215546Sopenharmony_ci * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. 2320bf215546Sopenharmony_ci * \param name the transform feedback object 2321bf215546Sopenharmony_ci * User still has to setup of the vertex attribute info with 2322bf215546Sopenharmony_ci * glVertexPointer, glColorPointer, etc. 2323bf215546Sopenharmony_ci * Part of GL_ARB_transform_feedback2. 2324bf215546Sopenharmony_ci */ 2325bf215546Sopenharmony_civoid GLAPIENTRY 2326bf215546Sopenharmony_ci_mesa_DrawTransformFeedback(GLenum mode, GLuint name) 2327bf215546Sopenharmony_ci{ 2328bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2329bf215546Sopenharmony_ci struct gl_transform_feedback_object *obj = 2330bf215546Sopenharmony_ci _mesa_lookup_transform_feedback_object(ctx, name); 2331bf215546Sopenharmony_ci 2332bf215546Sopenharmony_ci _mesa_draw_transform_feedback(ctx, mode, obj, 0, 1); 2333bf215546Sopenharmony_ci} 2334bf215546Sopenharmony_ci 2335bf215546Sopenharmony_ci 2336bf215546Sopenharmony_civoid GLAPIENTRY 2337bf215546Sopenharmony_ci_mesa_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream) 2338bf215546Sopenharmony_ci{ 2339bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2340bf215546Sopenharmony_ci struct gl_transform_feedback_object *obj = 2341bf215546Sopenharmony_ci _mesa_lookup_transform_feedback_object(ctx, name); 2342bf215546Sopenharmony_ci 2343bf215546Sopenharmony_ci _mesa_draw_transform_feedback(ctx, mode, obj, stream, 1); 2344bf215546Sopenharmony_ci} 2345bf215546Sopenharmony_ci 2346bf215546Sopenharmony_ci 2347bf215546Sopenharmony_civoid GLAPIENTRY 2348bf215546Sopenharmony_ci_mesa_DrawTransformFeedbackInstanced(GLenum mode, GLuint name, 2349bf215546Sopenharmony_ci GLsizei primcount) 2350bf215546Sopenharmony_ci{ 2351bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2352bf215546Sopenharmony_ci struct gl_transform_feedback_object *obj = 2353bf215546Sopenharmony_ci _mesa_lookup_transform_feedback_object(ctx, name); 2354bf215546Sopenharmony_ci 2355bf215546Sopenharmony_ci _mesa_draw_transform_feedback(ctx, mode, obj, 0, primcount); 2356bf215546Sopenharmony_ci} 2357bf215546Sopenharmony_ci 2358bf215546Sopenharmony_ci 2359bf215546Sopenharmony_civoid GLAPIENTRY 2360bf215546Sopenharmony_ci_mesa_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name, 2361bf215546Sopenharmony_ci GLuint stream, 2362bf215546Sopenharmony_ci GLsizei primcount) 2363bf215546Sopenharmony_ci{ 2364bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2365bf215546Sopenharmony_ci struct gl_transform_feedback_object *obj = 2366bf215546Sopenharmony_ci _mesa_lookup_transform_feedback_object(ctx, name); 2367bf215546Sopenharmony_ci 2368bf215546Sopenharmony_ci _mesa_draw_transform_feedback(ctx, mode, obj, stream, primcount); 2369bf215546Sopenharmony_ci} 2370bf215546Sopenharmony_ci 2371bf215546Sopenharmony_ci 2372bf215546Sopenharmony_cistatic void 2373bf215546Sopenharmony_ci_mesa_validated_multidrawarraysindirect(struct gl_context *ctx, GLenum mode, 2374bf215546Sopenharmony_ci GLintptr indirect, 2375bf215546Sopenharmony_ci GLintptr drawcount_offset, 2376bf215546Sopenharmony_ci GLsizei drawcount, GLsizei stride, 2377bf215546Sopenharmony_ci struct gl_buffer_object *drawcount_buffer) 2378bf215546Sopenharmony_ci{ 2379bf215546Sopenharmony_ci /* If drawcount_buffer is set, drawcount is the maximum draw count.*/ 2380bf215546Sopenharmony_ci if (drawcount == 0) 2381bf215546Sopenharmony_ci return; 2382bf215546Sopenharmony_ci 2383bf215546Sopenharmony_ci st_indirect_draw_vbo(ctx, mode, ctx->DrawIndirectBuffer, indirect, 2384bf215546Sopenharmony_ci drawcount, stride, drawcount_buffer, 2385bf215546Sopenharmony_ci drawcount_offset, NULL, false, 0); 2386bf215546Sopenharmony_ci 2387bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 2388bf215546Sopenharmony_ci _mesa_flush(ctx); 2389bf215546Sopenharmony_ci} 2390bf215546Sopenharmony_ci 2391bf215546Sopenharmony_ci 2392bf215546Sopenharmony_cistatic void 2393bf215546Sopenharmony_ci_mesa_validated_multidrawelementsindirect(struct gl_context *ctx, 2394bf215546Sopenharmony_ci GLenum mode, GLenum type, 2395bf215546Sopenharmony_ci GLintptr indirect, 2396bf215546Sopenharmony_ci GLintptr drawcount_offset, 2397bf215546Sopenharmony_ci GLsizei drawcount, GLsizei stride, 2398bf215546Sopenharmony_ci struct gl_buffer_object *drawcount_buffer) 2399bf215546Sopenharmony_ci{ 2400bf215546Sopenharmony_ci /* If drawcount_buffer is set, drawcount is the maximum draw count.*/ 2401bf215546Sopenharmony_ci if (drawcount == 0) 2402bf215546Sopenharmony_ci return; 2403bf215546Sopenharmony_ci 2404bf215546Sopenharmony_ci /* NOTE: IndexBufferObj is guaranteed to be a VBO. */ 2405bf215546Sopenharmony_ci struct _mesa_index_buffer ib; 2406bf215546Sopenharmony_ci ib.count = 0; /* unknown */ 2407bf215546Sopenharmony_ci ib.obj = ctx->Array.VAO->IndexBufferObj; 2408bf215546Sopenharmony_ci ib.ptr = NULL; 2409bf215546Sopenharmony_ci ib.index_size_shift = get_index_size_shift(type); 2410bf215546Sopenharmony_ci 2411bf215546Sopenharmony_ci st_indirect_draw_vbo(ctx, mode, ctx->DrawIndirectBuffer, indirect, 2412bf215546Sopenharmony_ci drawcount, stride, drawcount_buffer, 2413bf215546Sopenharmony_ci drawcount_offset, &ib, 2414bf215546Sopenharmony_ci ctx->Array._PrimitiveRestart[ib.index_size_shift], 2415bf215546Sopenharmony_ci ctx->Array._RestartIndex[ib.index_size_shift]); 2416bf215546Sopenharmony_ci 2417bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 2418bf215546Sopenharmony_ci _mesa_flush(ctx); 2419bf215546Sopenharmony_ci} 2420bf215546Sopenharmony_ci 2421bf215546Sopenharmony_ci 2422bf215546Sopenharmony_ci/** 2423bf215546Sopenharmony_ci * Like [Multi]DrawArrays/Elements, but they take most arguments from 2424bf215546Sopenharmony_ci * a buffer object. 2425bf215546Sopenharmony_ci */ 2426bf215546Sopenharmony_civoid GLAPIENTRY 2427bf215546Sopenharmony_ci_mesa_DrawArraysIndirect(GLenum mode, const GLvoid *indirect) 2428bf215546Sopenharmony_ci{ 2429bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2430bf215546Sopenharmony_ci 2431bf215546Sopenharmony_ci /* From the ARB_draw_indirect spec: 2432bf215546Sopenharmony_ci * 2433bf215546Sopenharmony_ci * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 2434bf215546Sopenharmony_ci * compatibility profile, this indicates that DrawArraysIndirect and 2435bf215546Sopenharmony_ci * DrawElementsIndirect are to source their arguments directly from the 2436bf215546Sopenharmony_ci * pointer passed as their <indirect> parameters." 2437bf215546Sopenharmony_ci */ 2438bf215546Sopenharmony_ci if (ctx->API == API_OPENGL_COMPAT && 2439bf215546Sopenharmony_ci !ctx->DrawIndirectBuffer) { 2440bf215546Sopenharmony_ci DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect; 2441bf215546Sopenharmony_ci 2442bf215546Sopenharmony_ci _mesa_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count, 2443bf215546Sopenharmony_ci cmd->primCount, 2444bf215546Sopenharmony_ci cmd->baseInstance); 2445bf215546Sopenharmony_ci return; 2446bf215546Sopenharmony_ci } 2447bf215546Sopenharmony_ci 2448bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2449bf215546Sopenharmony_ci 2450bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2451bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2452bf215546Sopenharmony_ci 2453bf215546Sopenharmony_ci if (ctx->NewState) 2454bf215546Sopenharmony_ci _mesa_update_state(ctx); 2455bf215546Sopenharmony_ci 2456bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2457bf215546Sopenharmony_ci !_mesa_validate_DrawArraysIndirect(ctx, mode, indirect)) 2458bf215546Sopenharmony_ci return; 2459bf215546Sopenharmony_ci 2460bf215546Sopenharmony_ci _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect, 2461bf215546Sopenharmony_ci 0, 1, 16, NULL); 2462bf215546Sopenharmony_ci} 2463bf215546Sopenharmony_ci 2464bf215546Sopenharmony_ci 2465bf215546Sopenharmony_civoid GLAPIENTRY 2466bf215546Sopenharmony_ci_mesa_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) 2467bf215546Sopenharmony_ci{ 2468bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2469bf215546Sopenharmony_ci 2470bf215546Sopenharmony_ci /* From the ARB_draw_indirect spec: 2471bf215546Sopenharmony_ci * 2472bf215546Sopenharmony_ci * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 2473bf215546Sopenharmony_ci * compatibility profile, this indicates that DrawArraysIndirect and 2474bf215546Sopenharmony_ci * DrawElementsIndirect are to source their arguments directly from the 2475bf215546Sopenharmony_ci * pointer passed as their <indirect> parameters." 2476bf215546Sopenharmony_ci */ 2477bf215546Sopenharmony_ci if (ctx->API == API_OPENGL_COMPAT && 2478bf215546Sopenharmony_ci !ctx->DrawIndirectBuffer) { 2479bf215546Sopenharmony_ci /* 2480bf215546Sopenharmony_ci * Unlike regular DrawElementsInstancedBaseVertex commands, the indices 2481bf215546Sopenharmony_ci * may not come from a client array and must come from an index buffer. 2482bf215546Sopenharmony_ci * If no element array buffer is bound, an INVALID_OPERATION error is 2483bf215546Sopenharmony_ci * generated. 2484bf215546Sopenharmony_ci */ 2485bf215546Sopenharmony_ci if (!ctx->Array.VAO->IndexBufferObj) { 2486bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, 2487bf215546Sopenharmony_ci "glDrawElementsIndirect(no buffer bound " 2488bf215546Sopenharmony_ci "to GL_ELEMENT_ARRAY_BUFFER)"); 2489bf215546Sopenharmony_ci } else { 2490bf215546Sopenharmony_ci DrawElementsIndirectCommand *cmd = 2491bf215546Sopenharmony_ci (DrawElementsIndirectCommand *) indirect; 2492bf215546Sopenharmony_ci 2493bf215546Sopenharmony_ci /* Convert offset to pointer */ 2494bf215546Sopenharmony_ci void *offset = (void *) 2495bf215546Sopenharmony_ci (uintptr_t)((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL); 2496bf215546Sopenharmony_ci 2497bf215546Sopenharmony_ci _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count, 2498bf215546Sopenharmony_ci type, offset, 2499bf215546Sopenharmony_ci cmd->primCount, 2500bf215546Sopenharmony_ci cmd->baseVertex, 2501bf215546Sopenharmony_ci cmd->baseInstance); 2502bf215546Sopenharmony_ci } 2503bf215546Sopenharmony_ci 2504bf215546Sopenharmony_ci return; 2505bf215546Sopenharmony_ci } 2506bf215546Sopenharmony_ci 2507bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2508bf215546Sopenharmony_ci 2509bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2510bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2511bf215546Sopenharmony_ci 2512bf215546Sopenharmony_ci if (ctx->NewState) 2513bf215546Sopenharmony_ci _mesa_update_state(ctx); 2514bf215546Sopenharmony_ci 2515bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2516bf215546Sopenharmony_ci !_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect)) 2517bf215546Sopenharmony_ci return; 2518bf215546Sopenharmony_ci 2519bf215546Sopenharmony_ci _mesa_validated_multidrawelementsindirect(ctx, mode, type, 2520bf215546Sopenharmony_ci (GLintptr)indirect, 0, 2521bf215546Sopenharmony_ci 1, 20, NULL); 2522bf215546Sopenharmony_ci} 2523bf215546Sopenharmony_ci 2524bf215546Sopenharmony_ci 2525bf215546Sopenharmony_civoid GLAPIENTRY 2526bf215546Sopenharmony_ci_mesa_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, 2527bf215546Sopenharmony_ci GLsizei primcount, GLsizei stride) 2528bf215546Sopenharmony_ci{ 2529bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2530bf215546Sopenharmony_ci 2531bf215546Sopenharmony_ci /* If <stride> is zero, the array elements are treated as tightly packed. */ 2532bf215546Sopenharmony_ci if (stride == 0) 2533bf215546Sopenharmony_ci stride = sizeof(DrawArraysIndirectCommand); 2534bf215546Sopenharmony_ci 2535bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2536bf215546Sopenharmony_ci 2537bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2538bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2539bf215546Sopenharmony_ci 2540bf215546Sopenharmony_ci if (ctx->NewState) 2541bf215546Sopenharmony_ci _mesa_update_state(ctx); 2542bf215546Sopenharmony_ci 2543bf215546Sopenharmony_ci /* From the ARB_draw_indirect spec: 2544bf215546Sopenharmony_ci * 2545bf215546Sopenharmony_ci * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 2546bf215546Sopenharmony_ci * compatibility profile, this indicates that DrawArraysIndirect and 2547bf215546Sopenharmony_ci * DrawElementsIndirect are to source their arguments directly from the 2548bf215546Sopenharmony_ci * pointer passed as their <indirect> parameters." 2549bf215546Sopenharmony_ci */ 2550bf215546Sopenharmony_ci if (ctx->API == API_OPENGL_COMPAT && 2551bf215546Sopenharmony_ci !ctx->DrawIndirectBuffer) { 2552bf215546Sopenharmony_ci 2553bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2554bf215546Sopenharmony_ci (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, 2555bf215546Sopenharmony_ci "glMultiDrawArraysIndirect") || 2556bf215546Sopenharmony_ci !_mesa_validate_DrawArrays(ctx, mode, 1))) 2557bf215546Sopenharmony_ci return; 2558bf215546Sopenharmony_ci 2559bf215546Sopenharmony_ci struct pipe_draw_info info; 2560bf215546Sopenharmony_ci info.mode = mode; 2561bf215546Sopenharmony_ci info.index_size = 0; 2562bf215546Sopenharmony_ci info.view_mask = 0; 2563bf215546Sopenharmony_ci /* Packed section begin. */ 2564bf215546Sopenharmony_ci info.primitive_restart = false; 2565bf215546Sopenharmony_ci info.has_user_indices = false; 2566bf215546Sopenharmony_ci info.index_bounds_valid = false; 2567bf215546Sopenharmony_ci info.increment_draw_id = primcount > 1; 2568bf215546Sopenharmony_ci info.was_line_loop = false; 2569bf215546Sopenharmony_ci info.take_index_buffer_ownership = false; 2570bf215546Sopenharmony_ci info.index_bias_varies = false; 2571bf215546Sopenharmony_ci /* Packed section end. */ 2572bf215546Sopenharmony_ci 2573bf215546Sopenharmony_ci const uint8_t *ptr = (const uint8_t *) indirect; 2574bf215546Sopenharmony_ci for (unsigned i = 0; i < primcount; i++) { 2575bf215546Sopenharmony_ci DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr; 2576bf215546Sopenharmony_ci 2577bf215546Sopenharmony_ci info.start_instance = cmd->baseInstance; 2578bf215546Sopenharmony_ci info.instance_count = cmd->primCount; 2579bf215546Sopenharmony_ci 2580bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 2581bf215546Sopenharmony_ci draw.start = cmd->first; 2582bf215546Sopenharmony_ci draw.count = cmd->count; 2583bf215546Sopenharmony_ci 2584bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1); 2585bf215546Sopenharmony_ci ptr += stride; 2586bf215546Sopenharmony_ci } 2587bf215546Sopenharmony_ci 2588bf215546Sopenharmony_ci return; 2589bf215546Sopenharmony_ci } 2590bf215546Sopenharmony_ci 2591bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2592bf215546Sopenharmony_ci !_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect, 2593bf215546Sopenharmony_ci primcount, stride)) 2594bf215546Sopenharmony_ci return; 2595bf215546Sopenharmony_ci 2596bf215546Sopenharmony_ci _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect, 0, 2597bf215546Sopenharmony_ci primcount, stride, NULL); 2598bf215546Sopenharmony_ci} 2599bf215546Sopenharmony_ci 2600bf215546Sopenharmony_ci 2601bf215546Sopenharmony_civoid GLAPIENTRY 2602bf215546Sopenharmony_ci_mesa_MultiDrawElementsIndirect(GLenum mode, GLenum type, 2603bf215546Sopenharmony_ci const GLvoid *indirect, 2604bf215546Sopenharmony_ci GLsizei primcount, GLsizei stride) 2605bf215546Sopenharmony_ci{ 2606bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2607bf215546Sopenharmony_ci 2608bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2609bf215546Sopenharmony_ci 2610bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2611bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2612bf215546Sopenharmony_ci 2613bf215546Sopenharmony_ci if (ctx->NewState) 2614bf215546Sopenharmony_ci _mesa_update_state(ctx); 2615bf215546Sopenharmony_ci 2616bf215546Sopenharmony_ci /* If <stride> is zero, the array elements are treated as tightly packed. */ 2617bf215546Sopenharmony_ci if (stride == 0) 2618bf215546Sopenharmony_ci stride = sizeof(DrawElementsIndirectCommand); 2619bf215546Sopenharmony_ci 2620bf215546Sopenharmony_ci /* From the ARB_draw_indirect spec: 2621bf215546Sopenharmony_ci * 2622bf215546Sopenharmony_ci * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 2623bf215546Sopenharmony_ci * compatibility profile, this indicates that DrawArraysIndirect and 2624bf215546Sopenharmony_ci * DrawElementsIndirect are to source their arguments directly from the 2625bf215546Sopenharmony_ci * pointer passed as their <indirect> parameters." 2626bf215546Sopenharmony_ci */ 2627bf215546Sopenharmony_ci if (ctx->API == API_OPENGL_COMPAT && 2628bf215546Sopenharmony_ci !ctx->DrawIndirectBuffer) { 2629bf215546Sopenharmony_ci /* 2630bf215546Sopenharmony_ci * Unlike regular DrawElementsInstancedBaseVertex commands, the indices 2631bf215546Sopenharmony_ci * may not come from a client array and must come from an index buffer. 2632bf215546Sopenharmony_ci * If no element array buffer is bound, an INVALID_OPERATION error is 2633bf215546Sopenharmony_ci * generated. 2634bf215546Sopenharmony_ci */ 2635bf215546Sopenharmony_ci if (!ctx->Array.VAO->IndexBufferObj) { 2636bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, 2637bf215546Sopenharmony_ci "glMultiDrawElementsIndirect(no buffer bound " 2638bf215546Sopenharmony_ci "to GL_ELEMENT_ARRAY_BUFFER)"); 2639bf215546Sopenharmony_ci 2640bf215546Sopenharmony_ci return; 2641bf215546Sopenharmony_ci } 2642bf215546Sopenharmony_ci 2643bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2644bf215546Sopenharmony_ci (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, 2645bf215546Sopenharmony_ci "glMultiDrawArraysIndirect") || 2646bf215546Sopenharmony_ci !_mesa_validate_DrawElements(ctx, mode, 1, type))) 2647bf215546Sopenharmony_ci return; 2648bf215546Sopenharmony_ci 2649bf215546Sopenharmony_ci unsigned index_size_shift = get_index_size_shift(type); 2650bf215546Sopenharmony_ci 2651bf215546Sopenharmony_ci struct pipe_draw_info info; 2652bf215546Sopenharmony_ci info.mode = mode; 2653bf215546Sopenharmony_ci info.index_size = 1 << index_size_shift; 2654bf215546Sopenharmony_ci info.view_mask = 0; 2655bf215546Sopenharmony_ci /* Packed section begin. */ 2656bf215546Sopenharmony_ci info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift]; 2657bf215546Sopenharmony_ci info.has_user_indices = false; 2658bf215546Sopenharmony_ci info.index_bounds_valid = false; 2659bf215546Sopenharmony_ci info.increment_draw_id = primcount > 1; 2660bf215546Sopenharmony_ci info.was_line_loop = false; 2661bf215546Sopenharmony_ci info.take_index_buffer_ownership = false; 2662bf215546Sopenharmony_ci info.index_bias_varies = false; 2663bf215546Sopenharmony_ci /* Packed section end. */ 2664bf215546Sopenharmony_ci info.restart_index = ctx->Array._RestartIndex[index_size_shift]; 2665bf215546Sopenharmony_ci 2666bf215546Sopenharmony_ci const uint8_t *ptr = (const uint8_t *) indirect; 2667bf215546Sopenharmony_ci for (unsigned i = 0; i < primcount; i++) { 2668bf215546Sopenharmony_ci DrawElementsIndirectCommand *cmd = (DrawElementsIndirectCommand*)ptr; 2669bf215546Sopenharmony_ci 2670bf215546Sopenharmony_ci info.index.gl_bo = ctx->Array.VAO->IndexBufferObj; 2671bf215546Sopenharmony_ci info.start_instance = cmd->baseInstance; 2672bf215546Sopenharmony_ci info.instance_count = cmd->primCount; 2673bf215546Sopenharmony_ci 2674bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 2675bf215546Sopenharmony_ci draw.start = cmd->firstIndex; 2676bf215546Sopenharmony_ci draw.count = cmd->count; 2677bf215546Sopenharmony_ci draw.index_bias = cmd->baseVertex; 2678bf215546Sopenharmony_ci 2679bf215546Sopenharmony_ci ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1); 2680bf215546Sopenharmony_ci ptr += stride; 2681bf215546Sopenharmony_ci } 2682bf215546Sopenharmony_ci 2683bf215546Sopenharmony_ci return; 2684bf215546Sopenharmony_ci } 2685bf215546Sopenharmony_ci 2686bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2687bf215546Sopenharmony_ci !_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect, 2688bf215546Sopenharmony_ci primcount, stride)) 2689bf215546Sopenharmony_ci return; 2690bf215546Sopenharmony_ci 2691bf215546Sopenharmony_ci _mesa_validated_multidrawelementsindirect(ctx, mode, type, 2692bf215546Sopenharmony_ci (GLintptr)indirect, 0, primcount, 2693bf215546Sopenharmony_ci stride, NULL); 2694bf215546Sopenharmony_ci} 2695bf215546Sopenharmony_ci 2696bf215546Sopenharmony_ci 2697bf215546Sopenharmony_civoid GLAPIENTRY 2698bf215546Sopenharmony_ci_mesa_MultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect, 2699bf215546Sopenharmony_ci GLintptr drawcount_offset, 2700bf215546Sopenharmony_ci GLsizei maxdrawcount, GLsizei stride) 2701bf215546Sopenharmony_ci{ 2702bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2703bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2704bf215546Sopenharmony_ci 2705bf215546Sopenharmony_ci /* If <stride> is zero, the array elements are treated as tightly packed. */ 2706bf215546Sopenharmony_ci if (stride == 0) 2707bf215546Sopenharmony_ci stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ 2708bf215546Sopenharmony_ci 2709bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2710bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2711bf215546Sopenharmony_ci 2712bf215546Sopenharmony_ci if (ctx->NewState) 2713bf215546Sopenharmony_ci _mesa_update_state(ctx); 2714bf215546Sopenharmony_ci 2715bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2716bf215546Sopenharmony_ci !_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, indirect, 2717bf215546Sopenharmony_ci drawcount_offset, 2718bf215546Sopenharmony_ci maxdrawcount, stride)) 2719bf215546Sopenharmony_ci return; 2720bf215546Sopenharmony_ci 2721bf215546Sopenharmony_ci _mesa_validated_multidrawarraysindirect(ctx, mode, indirect, 2722bf215546Sopenharmony_ci drawcount_offset, maxdrawcount, 2723bf215546Sopenharmony_ci stride, ctx->ParameterBuffer); 2724bf215546Sopenharmony_ci} 2725bf215546Sopenharmony_ci 2726bf215546Sopenharmony_ci 2727bf215546Sopenharmony_civoid GLAPIENTRY 2728bf215546Sopenharmony_ci_mesa_MultiDrawElementsIndirectCountARB(GLenum mode, GLenum type, 2729bf215546Sopenharmony_ci GLintptr indirect, 2730bf215546Sopenharmony_ci GLintptr drawcount_offset, 2731bf215546Sopenharmony_ci GLsizei maxdrawcount, GLsizei stride) 2732bf215546Sopenharmony_ci{ 2733bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2734bf215546Sopenharmony_ci FLUSH_FOR_DRAW(ctx); 2735bf215546Sopenharmony_ci 2736bf215546Sopenharmony_ci /* If <stride> is zero, the array elements are treated as tightly packed. */ 2737bf215546Sopenharmony_ci if (stride == 0) 2738bf215546Sopenharmony_ci stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ 2739bf215546Sopenharmony_ci 2740bf215546Sopenharmony_ci _mesa_set_draw_vao(ctx, ctx->Array.VAO, 2741bf215546Sopenharmony_ci ctx->VertexProgram._VPModeInputFilter); 2742bf215546Sopenharmony_ci 2743bf215546Sopenharmony_ci if (ctx->NewState) 2744bf215546Sopenharmony_ci _mesa_update_state(ctx); 2745bf215546Sopenharmony_ci 2746bf215546Sopenharmony_ci if (!_mesa_is_no_error_enabled(ctx) && 2747bf215546Sopenharmony_ci !_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type, 2748bf215546Sopenharmony_ci indirect, 2749bf215546Sopenharmony_ci drawcount_offset, 2750bf215546Sopenharmony_ci maxdrawcount, stride)) 2751bf215546Sopenharmony_ci return; 2752bf215546Sopenharmony_ci 2753bf215546Sopenharmony_ci _mesa_validated_multidrawelementsindirect(ctx, mode, type, indirect, 2754bf215546Sopenharmony_ci drawcount_offset, maxdrawcount, 2755bf215546Sopenharmony_ci stride, ctx->ParameterBuffer); 2756bf215546Sopenharmony_ci} 2757bf215546Sopenharmony_ci 2758bf215546Sopenharmony_ci 2759bf215546Sopenharmony_ci/* GL_IBM_multimode_draw_arrays */ 2760bf215546Sopenharmony_civoid GLAPIENTRY 2761bf215546Sopenharmony_ci_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first, 2762bf215546Sopenharmony_ci const GLsizei * count, 2763bf215546Sopenharmony_ci GLsizei primcount, GLint modestride ) 2764bf215546Sopenharmony_ci{ 2765bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2766bf215546Sopenharmony_ci GLint i; 2767bf215546Sopenharmony_ci 2768bf215546Sopenharmony_ci for ( i = 0 ; i < primcount ; i++ ) { 2769bf215546Sopenharmony_ci if ( count[i] > 0 ) { 2770bf215546Sopenharmony_ci GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); 2771bf215546Sopenharmony_ci CALL_DrawArrays(ctx->CurrentServerDispatch, ( m, first[i], count[i] )); 2772bf215546Sopenharmony_ci } 2773bf215546Sopenharmony_ci } 2774bf215546Sopenharmony_ci} 2775bf215546Sopenharmony_ci 2776bf215546Sopenharmony_ci 2777bf215546Sopenharmony_ci/* GL_IBM_multimode_draw_arrays */ 2778bf215546Sopenharmony_civoid GLAPIENTRY 2779bf215546Sopenharmony_ci_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count, 2780bf215546Sopenharmony_ci GLenum type, const GLvoid * const * indices, 2781bf215546Sopenharmony_ci GLsizei primcount, GLint modestride ) 2782bf215546Sopenharmony_ci{ 2783bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 2784bf215546Sopenharmony_ci GLint i; 2785bf215546Sopenharmony_ci 2786bf215546Sopenharmony_ci for ( i = 0 ; i < primcount ; i++ ) { 2787bf215546Sopenharmony_ci if ( count[i] > 0 ) { 2788bf215546Sopenharmony_ci GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); 2789bf215546Sopenharmony_ci CALL_DrawElements(ctx->CurrentServerDispatch, ( m, count[i], type, 2790bf215546Sopenharmony_ci indices[i] )); 2791bf215546Sopenharmony_ci } 2792bf215546Sopenharmony_ci } 2793bf215546Sopenharmony_ci} 2794