1 /*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 /** \file glthread_marshal.h
25 *
26 * Declarations of functions related to marshalling GL calls from a client
27 * thread to a server thread.
28 */
29
30 #ifndef MARSHAL_H
31 #define MARSHAL_H
32
33 #include "main/glthread.h"
34 #include "main/context.h"
35 #include "main/macros.h"
36 #include "main/matrix.h"
37
38 /* 32-bit signed integer clamped to 0..UINT16_MAX to compress parameters
39 * for glthread. All values < 0 and >= UINT16_MAX are expected to throw
40 * GL_INVALID_VALUE. Negative values are mapped to UINT16_MAX.
41 */
42 typedef uint16_t GLpacked16i;
43
44 /* 32-bit signed integer clamped to 16 bits. */
45 typedef int16_t GLclamped16i;
46
47 struct marshal_cmd_base
48 {
49 /**
50 * Type of command. See enum marshal_dispatch_cmd_id.
51 */
52 uint16_t cmd_id;
53 };
54
55 /* This must be included after "struct marshal_cmd_base" because it uses it. */
56 #include "marshal_generated.h"
57
58 typedef uint32_t (*_mesa_unmarshal_func)(struct gl_context *ctx,
59 const void *restrict cmd);
60 extern const _mesa_unmarshal_func _mesa_unmarshal_dispatch[NUM_DISPATCH_CMD];
61 extern const char *_mesa_unmarshal_func_name[NUM_DISPATCH_CMD];
62
63 struct marshal_cmd_DrawElementsUserBuf
64 {
65 struct marshal_cmd_base cmd_base;
66 GLenum8 mode;
67 GLindextype type;
68 uint16_t num_slots;
69 GLsizei count;
70 GLsizei instance_count;
71 GLint basevertex;
72 GLuint baseinstance;
73 GLuint drawid;
74 GLuint user_buffer_mask;
75 const GLvoid *indices;
76 struct gl_buffer_object *index_buffer;
77 };
78
79 struct marshal_cmd_DrawElementsUserBufPacked
80 {
81 struct marshal_cmd_base cmd_base;
82 GLenum8 mode;
83 GLindextype type;
84 uint16_t num_slots;
85 GLushort count;
86 GLuint user_buffer_mask;
87 GLuint indices;
88 struct gl_buffer_object *index_buffer;
89 };
90
91 static inline void *
_mesa_glthread_allocate_command(struct gl_context * ctx,uint16_t cmd_id,unsigned size)92 _mesa_glthread_allocate_command(struct gl_context *ctx,
93 uint16_t cmd_id,
94 unsigned size)
95 {
96 struct glthread_state *glthread = &ctx->GLThread;
97 const unsigned num_elements = align(size, 8) / 8;
98
99 assert (num_elements <= MARSHAL_MAX_CMD_SIZE / 8);
100
101 if (unlikely(glthread->used + num_elements > MARSHAL_MAX_CMD_SIZE / 8))
102 _mesa_glthread_flush_batch(ctx);
103
104 struct glthread_batch *next = glthread->next_batch;
105 struct marshal_cmd_base *cmd_base =
106 (struct marshal_cmd_base *)&next->buffer[glthread->used];
107 glthread->used += num_elements;
108 cmd_base->cmd_id = cmd_id;
109 return cmd_base;
110 }
111
112 static inline GLenum
_mesa_decode_index_type(GLindextype type)113 _mesa_decode_index_type(GLindextype type)
114 {
115 return (GLenum)type.value + GL_UNSIGNED_BYTE - 1;
116 }
117
118 static inline struct marshal_cmd_base *
_mesa_glthread_get_cmd(uint64_t * opaque_cmd)119 _mesa_glthread_get_cmd(uint64_t *opaque_cmd)
120 {
121 return (struct marshal_cmd_base*)opaque_cmd;
122 }
123
124 static inline uint64_t *
_mesa_glthread_next_cmd(uint64_t * opaque_cmd,unsigned cmd_size)125 _mesa_glthread_next_cmd(uint64_t *opaque_cmd, unsigned cmd_size)
126 {
127 return opaque_cmd + cmd_size;
128 }
129
130 static inline bool
_mesa_glthread_call_is_last(struct glthread_state * glthread,struct marshal_cmd_base * last,uint16_t num_slots)131 _mesa_glthread_call_is_last(struct glthread_state *glthread,
132 struct marshal_cmd_base *last, uint16_t num_slots)
133 {
134 return last &&
135 (uint64_t*)last + num_slots ==
136 &glthread->next_batch->buffer[glthread->used];
137 }
138
139 static inline bool
_mesa_glthread_has_pack_buffer(const struct gl_context * ctx)140 _mesa_glthread_has_pack_buffer(const struct gl_context *ctx)
141 {
142 return ctx->GLThread.CurrentPixelPackBufferName != 0;
143 }
144
145 static inline bool
_mesa_glthread_has_unpack_buffer(const struct gl_context * ctx)146 _mesa_glthread_has_unpack_buffer(const struct gl_context *ctx)
147 {
148 return ctx->GLThread.CurrentPixelUnpackBufferName != 0;
149 }
150
151 static inline unsigned
_mesa_buffer_enum_to_count(GLenum buffer)152 _mesa_buffer_enum_to_count(GLenum buffer)
153 {
154 switch (buffer) {
155 case GL_COLOR:
156 return 4;
157 case GL_DEPTH_STENCIL:
158 return 2;
159 case GL_STENCIL:
160 case GL_DEPTH:
161 return 1;
162 default:
163 return 0;
164 }
165 }
166
167 static inline unsigned
_mesa_tex_param_enum_to_count(GLenum pname)168 _mesa_tex_param_enum_to_count(GLenum pname)
169 {
170 switch (pname) {
171 case GL_TEXTURE_MIN_FILTER:
172 case GL_TEXTURE_MAG_FILTER:
173 case GL_TEXTURE_WRAP_S:
174 case GL_TEXTURE_WRAP_T:
175 case GL_TEXTURE_WRAP_R:
176 case GL_TEXTURE_BASE_LEVEL:
177 case GL_TEXTURE_MAX_LEVEL:
178 case GL_GENERATE_MIPMAP_SGIS:
179 case GL_TEXTURE_COMPARE_MODE_ARB:
180 case GL_TEXTURE_COMPARE_FUNC_ARB:
181 case GL_DEPTH_TEXTURE_MODE_ARB:
182 case GL_DEPTH_STENCIL_TEXTURE_MODE:
183 case GL_TEXTURE_SRGB_DECODE_EXT:
184 case GL_TEXTURE_REDUCTION_MODE_EXT:
185 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
186 case GL_TEXTURE_SWIZZLE_R:
187 case GL_TEXTURE_SWIZZLE_G:
188 case GL_TEXTURE_SWIZZLE_B:
189 case GL_TEXTURE_SWIZZLE_A:
190 case GL_TEXTURE_MIN_LOD:
191 case GL_TEXTURE_MAX_LOD:
192 case GL_TEXTURE_PRIORITY:
193 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
194 case GL_TEXTURE_LOD_BIAS:
195 case GL_TEXTURE_TILING_EXT:
196 case GL_TEXTURE_SPARSE_ARB:
197 case GL_VIRTUAL_PAGE_SIZE_INDEX_ARB:
198 case GL_NUM_SPARSE_LEVELS_ARB:
199 return 1;
200 case GL_TEXTURE_CROP_RECT_OES:
201 case GL_TEXTURE_SWIZZLE_RGBA:
202 case GL_TEXTURE_BORDER_COLOR:
203 return 4;
204 default:
205 return 0;
206 }
207 }
208
209 static inline unsigned
_mesa_fog_enum_to_count(GLenum pname)210 _mesa_fog_enum_to_count(GLenum pname)
211 {
212 switch (pname) {
213 case GL_FOG_MODE:
214 case GL_FOG_DENSITY:
215 case GL_FOG_START:
216 case GL_FOG_END:
217 case GL_FOG_INDEX:
218 case GL_FOG_COORDINATE_SOURCE_EXT:
219 case GL_FOG_DISTANCE_MODE_NV:
220 return 1;
221 case GL_FOG_COLOR:
222 return 4;
223 default:
224 return 0;
225 }
226 }
227
228 static inline unsigned
_mesa_light_enum_to_count(GLenum pname)229 _mesa_light_enum_to_count(GLenum pname)
230 {
231 switch (pname) {
232 case GL_AMBIENT:
233 case GL_DIFFUSE:
234 case GL_SPECULAR:
235 case GL_POSITION:
236 return 4;
237 case GL_SPOT_DIRECTION:
238 return 3;
239 case GL_SPOT_EXPONENT:
240 case GL_SPOT_CUTOFF:
241 case GL_CONSTANT_ATTENUATION:
242 case GL_LINEAR_ATTENUATION:
243 case GL_QUADRATIC_ATTENUATION:
244 return 1;
245 default:
246 return 0;
247 }
248 }
249
250 static inline unsigned
_mesa_light_model_enum_to_count(GLenum pname)251 _mesa_light_model_enum_to_count(GLenum pname)
252 {
253 switch (pname) {
254 case GL_LIGHT_MODEL_AMBIENT:
255 return 4;
256 case GL_LIGHT_MODEL_LOCAL_VIEWER:
257 case GL_LIGHT_MODEL_TWO_SIDE:
258 case GL_LIGHT_MODEL_COLOR_CONTROL:
259 return 1;
260 default:
261 return 0;
262 }
263 }
264
265 static inline unsigned
_mesa_texenv_enum_to_count(GLenum pname)266 _mesa_texenv_enum_to_count(GLenum pname)
267 {
268 switch (pname) {
269 case GL_TEXTURE_ENV_MODE:
270 case GL_COMBINE_RGB:
271 case GL_COMBINE_ALPHA:
272 case GL_SOURCE0_RGB:
273 case GL_SOURCE1_RGB:
274 case GL_SOURCE2_RGB:
275 case GL_SOURCE3_RGB_NV:
276 case GL_SOURCE0_ALPHA:
277 case GL_SOURCE1_ALPHA:
278 case GL_SOURCE2_ALPHA:
279 case GL_SOURCE3_ALPHA_NV:
280 case GL_OPERAND0_RGB:
281 case GL_OPERAND1_RGB:
282 case GL_OPERAND2_RGB:
283 case GL_OPERAND3_RGB_NV:
284 case GL_OPERAND0_ALPHA:
285 case GL_OPERAND1_ALPHA:
286 case GL_OPERAND2_ALPHA:
287 case GL_OPERAND3_ALPHA_NV:
288 case GL_RGB_SCALE:
289 case GL_ALPHA_SCALE:
290 case GL_TEXTURE_LOD_BIAS_EXT:
291 case GL_COORD_REPLACE:
292 return 1;
293 case GL_TEXTURE_ENV_COLOR:
294 return 4;
295 default:
296 return 0;
297 }
298 }
299
300 static inline unsigned
_mesa_texgen_enum_to_count(GLenum pname)301 _mesa_texgen_enum_to_count(GLenum pname)
302 {
303 switch (pname) {
304 case GL_TEXTURE_GEN_MODE:
305 return 1;
306 case GL_OBJECT_PLANE:
307 case GL_EYE_PLANE:
308 return 4;
309 default:
310 return 0;
311 }
312 }
313
314 static inline unsigned
_mesa_material_enum_to_count(GLenum pname)315 _mesa_material_enum_to_count(GLenum pname)
316 {
317 switch (pname) {
318 case GL_EMISSION:
319 case GL_AMBIENT:
320 case GL_DIFFUSE:
321 case GL_SPECULAR:
322 case GL_AMBIENT_AND_DIFFUSE:
323 return 4;
324 case GL_COLOR_INDEXES:
325 return 3;
326 case GL_SHININESS:
327 return 1;
328 default:
329 return 0;
330 }
331 }
332
333 static inline unsigned
_mesa_point_param_enum_to_count(GLenum pname)334 _mesa_point_param_enum_to_count(GLenum pname)
335 {
336 switch (pname) {
337 case GL_DISTANCE_ATTENUATION_EXT:
338 return 3;
339 case GL_POINT_SIZE_MIN_EXT:
340 case GL_POINT_SIZE_MAX_EXT:
341 case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
342 case GL_POINT_SPRITE_COORD_ORIGIN:
343 return 1;
344 default:
345 return 0;
346 }
347 }
348
349 static inline unsigned
_mesa_calllists_enum_to_count(GLenum type)350 _mesa_calllists_enum_to_count(GLenum type)
351 {
352 switch (type) {
353 case GL_BYTE:
354 case GL_UNSIGNED_BYTE:
355 return 1;
356 case GL_SHORT:
357 case GL_UNSIGNED_SHORT:
358 case GL_2_BYTES:
359 return 2;
360 case GL_3_BYTES:
361 return 3;
362 case GL_INT:
363 case GL_UNSIGNED_INT:
364 case GL_FLOAT:
365 case GL_4_BYTES:
366 return 4;
367 default:
368 return 0;
369 }
370 }
371
372 static inline unsigned
_mesa_patch_param_enum_to_count(GLenum pname)373 _mesa_patch_param_enum_to_count(GLenum pname)
374 {
375 switch (pname) {
376 case GL_PATCH_DEFAULT_OUTER_LEVEL:
377 return 4;
378 case GL_PATCH_DEFAULT_INNER_LEVEL:
379 return 2;
380 default:
381 return 0;
382 }
383 }
384
385 static inline unsigned
_mesa_memobj_enum_to_count(GLenum pname)386 _mesa_memobj_enum_to_count(GLenum pname)
387 {
388 switch (pname) {
389 case GL_DEDICATED_MEMORY_OBJECT_EXT:
390 return 1;
391 default:
392 return 0;
393 }
394 }
395
396 static inline unsigned
_mesa_semaphore_enum_to_count(GLenum pname)397 _mesa_semaphore_enum_to_count(GLenum pname)
398 {
399 switch (pname) {
400 /* EXT_semaphore and EXT_semaphore_fd define no parameters */
401 default:
402 return 0;
403 }
404 }
405
406 static inline gl_vert_attrib
_mesa_array_to_attrib(struct gl_context * ctx,GLenum array)407 _mesa_array_to_attrib(struct gl_context *ctx, GLenum array)
408 {
409 switch (array) {
410 case GL_VERTEX_ARRAY:
411 return VERT_ATTRIB_POS;
412 case GL_NORMAL_ARRAY:
413 return VERT_ATTRIB_NORMAL;
414 case GL_COLOR_ARRAY:
415 return VERT_ATTRIB_COLOR0;
416 case GL_INDEX_ARRAY:
417 return VERT_ATTRIB_COLOR_INDEX;
418 case GL_TEXTURE_COORD_ARRAY:
419 return VERT_ATTRIB_TEX(ctx->GLThread.ClientActiveTexture);
420 case GL_EDGE_FLAG_ARRAY:
421 return VERT_ATTRIB_EDGEFLAG;
422 case GL_FOG_COORDINATE_ARRAY:
423 return VERT_ATTRIB_FOG;
424 case GL_SECONDARY_COLOR_ARRAY:
425 return VERT_ATTRIB_COLOR1;
426 case GL_POINT_SIZE_ARRAY_OES:
427 return VERT_ATTRIB_POINT_SIZE;
428 case GL_PRIMITIVE_RESTART_NV:
429 return VERT_ATTRIB_PRIMITIVE_RESTART_NV;
430 default:
431 if (array >= GL_TEXTURE0 && array <= GL_TEXTURE7)
432 return VERT_ATTRIB_TEX(array - GL_TEXTURE0);
433 return VERT_ATTRIB_MAX;
434 }
435 }
436
437 static inline gl_matrix_index
_mesa_get_matrix_index(struct gl_context * ctx,GLenum mode)438 _mesa_get_matrix_index(struct gl_context *ctx, GLenum mode)
439 {
440 if (mode == GL_MODELVIEW || mode == GL_PROJECTION)
441 return M_MODELVIEW + (mode - GL_MODELVIEW);
442
443 if (mode == GL_TEXTURE)
444 return M_TEXTURE0 + ctx->GLThread.ActiveTexture;
445
446 if (mode >= GL_TEXTURE0 && mode <= GL_TEXTURE0 + MAX_TEXTURE_UNITS - 1)
447 return M_TEXTURE0 + (mode - GL_TEXTURE0);
448
449 if (mode >= GL_MATRIX0_ARB && mode <= GL_MATRIX0_ARB + MAX_PROGRAM_MATRICES - 1)
450 return M_PROGRAM0 + (mode - GL_MATRIX0_ARB);
451
452 return M_DUMMY;
453 }
454
455 static inline void
_mesa_glthread_Enable(struct gl_context * ctx,GLenum cap)456 _mesa_glthread_Enable(struct gl_context *ctx, GLenum cap)
457 {
458 if (ctx->GLThread.ListMode == GL_COMPILE)
459 return;
460
461 switch (cap) {
462 case GL_PRIMITIVE_RESTART:
463 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
464 _mesa_glthread_set_prim_restart(ctx, cap, true);
465 break;
466 case GL_BLEND:
467 ctx->GLThread.Blend = true;
468 break;
469 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
470 _mesa_glthread_disable(ctx);
471 ctx->GLThread.DebugOutputSynchronous = true;
472 break;
473 case GL_DEPTH_TEST:
474 ctx->GLThread.DepthTest = true;
475 break;
476 case GL_CULL_FACE:
477 ctx->GLThread.CullFace = true;
478 break;
479 case GL_LIGHTING:
480 ctx->GLThread.Lighting = true;
481 break;
482 case GL_POLYGON_STIPPLE:
483 ctx->GLThread.PolygonStipple = true;
484 break;
485 case GL_VERTEX_ARRAY:
486 case GL_NORMAL_ARRAY:
487 case GL_COLOR_ARRAY:
488 case GL_TEXTURE_COORD_ARRAY:
489 case GL_INDEX_ARRAY:
490 case GL_EDGE_FLAG_ARRAY:
491 case GL_FOG_COORDINATE_ARRAY:
492 case GL_SECONDARY_COLOR_ARRAY:
493 case GL_POINT_SIZE_ARRAY_OES:
494 _mesa_glthread_ClientState(ctx, NULL, _mesa_array_to_attrib(ctx, cap),
495 true);
496 break;
497 }
498 }
499
500 static inline void
_mesa_glthread_Disable(struct gl_context * ctx,GLenum cap)501 _mesa_glthread_Disable(struct gl_context *ctx, GLenum cap)
502 {
503 if (ctx->GLThread.ListMode == GL_COMPILE)
504 return;
505
506 switch (cap) {
507 case GL_PRIMITIVE_RESTART:
508 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
509 _mesa_glthread_set_prim_restart(ctx, cap, false);
510 break;
511 case GL_BLEND:
512 ctx->GLThread.Blend = false;
513 break;
514 case GL_CULL_FACE:
515 ctx->GLThread.CullFace = false;
516 break;
517 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
518 ctx->GLThread.DebugOutputSynchronous = false;
519 _mesa_glthread_enable(ctx);
520 break;
521 case GL_DEPTH_TEST:
522 ctx->GLThread.DepthTest = false;
523 break;
524 case GL_LIGHTING:
525 ctx->GLThread.Lighting = false;
526 break;
527 case GL_POLYGON_STIPPLE:
528 ctx->GLThread.PolygonStipple = false;
529 break;
530 case GL_VERTEX_ARRAY:
531 case GL_NORMAL_ARRAY:
532 case GL_COLOR_ARRAY:
533 case GL_TEXTURE_COORD_ARRAY:
534 case GL_INDEX_ARRAY:
535 case GL_EDGE_FLAG_ARRAY:
536 case GL_FOG_COORDINATE_ARRAY:
537 case GL_SECONDARY_COLOR_ARRAY:
538 case GL_POINT_SIZE_ARRAY_OES:
539 _mesa_glthread_ClientState(ctx, NULL, _mesa_array_to_attrib(ctx, cap),
540 false);
541 break;
542 }
543 }
544
545 static inline int
_mesa_glthread_IsEnabled(struct gl_context * ctx,GLenum cap)546 _mesa_glthread_IsEnabled(struct gl_context *ctx, GLenum cap)
547 {
548 /* This will generate GL_INVALID_OPERATION, as it should. */
549 if (ctx->GLThread.inside_begin_end)
550 return -1;
551
552 switch (cap) {
553 case GL_BLEND:
554 return ctx->GLThread.Blend;
555 case GL_CULL_FACE:
556 return ctx->GLThread.CullFace;
557 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
558 return ctx->GLThread.DebugOutputSynchronous;
559 case GL_DEPTH_TEST:
560 return ctx->GLThread.DepthTest;
561 case GL_LIGHTING:
562 return ctx->GLThread.Lighting;
563 case GL_POLYGON_STIPPLE:
564 return ctx->GLThread.PolygonStipple;
565 case GL_VERTEX_ARRAY:
566 return !!(ctx->GLThread.CurrentVAO->UserEnabled & VERT_BIT_POS);
567 case GL_NORMAL_ARRAY:
568 return !!(ctx->GLThread.CurrentVAO->UserEnabled & VERT_BIT_NORMAL);
569 case GL_COLOR_ARRAY:
570 return !!(ctx->GLThread.CurrentVAO->UserEnabled & VERT_BIT_COLOR0);
571 case GL_TEXTURE_COORD_ARRAY:
572 return !!(ctx->GLThread.CurrentVAO->UserEnabled &
573 (1 << VERT_ATTRIB_TEX(ctx->GLThread.ClientActiveTexture)));
574 default:
575 return -1; /* sync and call _mesa_IsEnabled. */
576 }
577 }
578
579 static inline void
_mesa_glthread_PushAttrib(struct gl_context * ctx,GLbitfield mask)580 _mesa_glthread_PushAttrib(struct gl_context *ctx, GLbitfield mask)
581 {
582 if (ctx->GLThread.ListMode == GL_COMPILE)
583 return;
584
585 if (ctx->GLThread.AttribStackDepth >= MAX_ATTRIB_STACK_DEPTH)
586 return;
587
588 struct glthread_attrib_node *attr =
589 &ctx->GLThread.AttribStack[ctx->GLThread.AttribStackDepth++];
590
591 attr->Mask = mask;
592
593 if (mask & GL_ENABLE_BIT)
594 attr->Blend = ctx->GLThread.Blend;
595
596 if (mask & (GL_POLYGON_BIT | GL_ENABLE_BIT)) {
597 attr->CullFace = ctx->GLThread.CullFace;
598 attr->PolygonStipple = ctx->GLThread.PolygonStipple;
599 }
600
601 if (mask & (GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT))
602 attr->DepthTest = ctx->GLThread.DepthTest;
603
604 if (mask & (GL_LIGHTING_BIT | GL_ENABLE_BIT))
605 attr->Lighting = ctx->GLThread.Lighting;
606
607 if (mask & GL_TEXTURE_BIT)
608 attr->ActiveTexture = ctx->GLThread.ActiveTexture;
609
610 if (mask & GL_TRANSFORM_BIT)
611 attr->MatrixMode = ctx->GLThread.MatrixMode;
612 }
613
614 static inline void
_mesa_glthread_PopAttrib(struct gl_context * ctx)615 _mesa_glthread_PopAttrib(struct gl_context *ctx)
616 {
617 if (ctx->GLThread.ListMode == GL_COMPILE)
618 return;
619
620 if (ctx->GLThread.AttribStackDepth == 0)
621 return;
622
623 struct glthread_attrib_node *attr =
624 &ctx->GLThread.AttribStack[--ctx->GLThread.AttribStackDepth];
625 unsigned mask = attr->Mask;
626
627 if (mask & GL_ENABLE_BIT)
628 ctx->GLThread.Blend = attr->Blend;
629
630 if (mask & (GL_POLYGON_BIT | GL_ENABLE_BIT)) {
631 ctx->GLThread.CullFace = attr->CullFace;
632 ctx->GLThread.PolygonStipple = attr->PolygonStipple;
633 }
634
635 if (mask & (GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT))
636 ctx->GLThread.DepthTest = attr->DepthTest;
637
638 if (mask & (GL_LIGHTING_BIT | GL_ENABLE_BIT))
639 ctx->GLThread.Lighting = attr->Lighting;
640
641 if (mask & GL_TEXTURE_BIT)
642 ctx->GLThread.ActiveTexture = attr->ActiveTexture;
643
644 if (mask & GL_TRANSFORM_BIT) {
645 ctx->GLThread.MatrixMode = attr->MatrixMode;
646 ctx->GLThread.MatrixIndex = _mesa_get_matrix_index(ctx, attr->MatrixMode);
647 }
648 }
649
650 static bool
is_matrix_stack_full(struct gl_context * ctx,gl_matrix_index idx)651 is_matrix_stack_full(struct gl_context *ctx, gl_matrix_index idx)
652 {
653 int max_stack_depth = 0;
654 if (M_MODELVIEW == ctx->GLThread.MatrixIndex) {
655 max_stack_depth = MAX_MODELVIEW_STACK_DEPTH;
656 } else if (M_PROJECTION == ctx->GLThread.MatrixIndex) {
657 max_stack_depth = MAX_PROJECTION_STACK_DEPTH;
658 } else if (M_PROGRAM_LAST >= ctx->GLThread.MatrixIndex) {
659 max_stack_depth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
660 } else if (M_TEXTURE_LAST >= ctx->GLThread.MatrixIndex) {
661 max_stack_depth = MAX_TEXTURE_STACK_DEPTH;
662 }
663 assert(max_stack_depth);
664
665 if (ctx->GLThread.MatrixStackDepth[idx] + 1 >= max_stack_depth)
666 return true;
667
668 return false;
669 }
670
671 static inline void
_mesa_glthread_MatrixPushEXT(struct gl_context * ctx,GLenum matrixMode)672 _mesa_glthread_MatrixPushEXT(struct gl_context *ctx, GLenum matrixMode)
673 {
674 if (ctx->GLThread.ListMode == GL_COMPILE)
675 return;
676
677 if (is_matrix_stack_full(ctx, _mesa_get_matrix_index(ctx, matrixMode)))
678 return;
679
680 ctx->GLThread.MatrixStackDepth[_mesa_get_matrix_index(ctx, matrixMode)]++;
681 }
682
683 static inline void
_mesa_glthread_MatrixPopEXT(struct gl_context * ctx,GLenum matrixMode)684 _mesa_glthread_MatrixPopEXT(struct gl_context *ctx, GLenum matrixMode)
685 {
686 if (ctx->GLThread.ListMode == GL_COMPILE)
687 return;
688
689 if (ctx->GLThread.MatrixStackDepth[_mesa_get_matrix_index(ctx, matrixMode)] == 0)
690 return;
691
692 ctx->GLThread.MatrixStackDepth[_mesa_get_matrix_index(ctx, matrixMode)]--;
693 }
694
695 static inline void
_mesa_glthread_ActiveTexture(struct gl_context * ctx,GLenum texture)696 _mesa_glthread_ActiveTexture(struct gl_context *ctx, GLenum texture)
697 {
698 if (ctx->GLThread.ListMode == GL_COMPILE)
699 return;
700
701 ctx->GLThread.ActiveTexture = texture - GL_TEXTURE0;
702 if (ctx->GLThread.MatrixMode == GL_TEXTURE)
703 ctx->GLThread.MatrixIndex = _mesa_get_matrix_index(ctx, texture);
704 }
705
706 static inline void
_mesa_glthread_PushMatrix(struct gl_context * ctx)707 _mesa_glthread_PushMatrix(struct gl_context *ctx)
708 {
709 if (ctx->GLThread.ListMode == GL_COMPILE)
710 return;
711
712 if (is_matrix_stack_full(ctx, ctx->GLThread.MatrixIndex))
713 return;
714
715 ctx->GLThread.MatrixStackDepth[ctx->GLThread.MatrixIndex]++;
716 }
717
718 static inline void
_mesa_glthread_PopMatrix(struct gl_context * ctx)719 _mesa_glthread_PopMatrix(struct gl_context *ctx)
720 {
721 if (ctx->GLThread.ListMode == GL_COMPILE)
722 return;
723
724 if (ctx->GLThread.MatrixStackDepth[ctx->GLThread.MatrixIndex] == 0)
725 return;
726
727 ctx->GLThread.MatrixStackDepth[ctx->GLThread.MatrixIndex]--;
728 }
729
730 static inline void
_mesa_glthread_MatrixMode(struct gl_context * ctx,GLenum mode)731 _mesa_glthread_MatrixMode(struct gl_context *ctx, GLenum mode)
732 {
733 if (ctx->GLThread.ListMode == GL_COMPILE)
734 return;
735
736 ctx->GLThread.MatrixIndex = _mesa_get_matrix_index(ctx, mode);
737 ctx->GLThread.MatrixMode = MIN2(mode, 0xffff);
738 }
739
740 static inline void
_mesa_glthread_ListBase(struct gl_context * ctx,GLuint base)741 _mesa_glthread_ListBase(struct gl_context *ctx, GLuint base)
742 {
743 if (ctx->GLThread.ListMode == GL_COMPILE)
744 return;
745
746 ctx->GLThread.ListBase = base;
747 }
748
749 static inline void
_mesa_glthread_init_call_fence(int * last_batch_index_where_called)750 _mesa_glthread_init_call_fence(int *last_batch_index_where_called)
751 {
752 *last_batch_index_where_called = -1;
753 }
754
755 static inline void
_mesa_glthread_fence_call(struct gl_context * ctx,int * last_batch_index_where_called)756 _mesa_glthread_fence_call(struct gl_context *ctx,
757 int *last_batch_index_where_called)
758 {
759 p_atomic_set(last_batch_index_where_called, ctx->GLThread.next);
760 /* Flush, so that the fenced call is last in the batch. */
761 _mesa_glthread_flush_batch(ctx);
762 }
763
764 static inline void
_mesa_glthread_signal_call(int * last_batch_index_where_called,int batch_index)765 _mesa_glthread_signal_call(int *last_batch_index_where_called, int batch_index)
766 {
767 /* Atomically set this to -1 if it's equal to batch_index. */
768 p_atomic_cmpxchg(last_batch_index_where_called, batch_index, -1);
769 }
770
771 static inline void
_mesa_glthread_wait_for_call(struct gl_context * ctx,int * last_batch_index_where_called)772 _mesa_glthread_wait_for_call(struct gl_context *ctx,
773 int *last_batch_index_where_called)
774 {
775 int batch = p_atomic_read(last_batch_index_where_called);
776 if (batch != -1) {
777 util_queue_fence_wait(&ctx->GLThread.batches[batch].fence);
778 assert(p_atomic_read(last_batch_index_where_called) == -1);
779 }
780 }
781
782 static inline void
_mesa_glthread_CallList(struct gl_context * ctx,GLuint list)783 _mesa_glthread_CallList(struct gl_context *ctx, GLuint list)
784 {
785 if (ctx->GLThread.ListMode == GL_COMPILE)
786 return;
787
788 /* Wait for all glEndList and glDeleteLists calls to finish to ensure that
789 * all display lists are up to date and the driver thread is not
790 * modifiying them. We will be executing them in the application thread.
791 */
792 _mesa_glthread_wait_for_call(ctx, &ctx->GLThread.LastDListChangeBatchIndex);
793
794 if (!ctx->Shared->DisplayListsAffectGLThread)
795 return;
796
797 /* Clear GL_COMPILE_AND_EXECUTE if needed. We only execute here. */
798 unsigned saved_mode = ctx->GLThread.ListMode;
799 ctx->GLThread.ListMode = 0;
800
801 _mesa_glthread_execute_list(ctx, list);
802
803 ctx->GLThread.ListMode = saved_mode;
804 }
805
806 static inline void
_mesa_glthread_CallLists(struct gl_context * ctx,GLsizei n,GLenum type,const GLvoid * lists)807 _mesa_glthread_CallLists(struct gl_context *ctx, GLsizei n, GLenum type,
808 const GLvoid *lists)
809 {
810 if (ctx->GLThread.ListMode == GL_COMPILE)
811 return;
812
813 if (n <= 0 || !lists)
814 return;
815
816 /* Wait for all glEndList and glDeleteLists calls to finish to ensure that
817 * all display lists are up to date and the driver thread is not
818 * modifiying them. We will be executing them in the application thread.
819 */
820 _mesa_glthread_wait_for_call(ctx, &ctx->GLThread.LastDListChangeBatchIndex);
821
822 /* Clear GL_COMPILE_AND_EXECUTE if needed. We only execute here. */
823 unsigned saved_mode = ctx->GLThread.ListMode;
824 ctx->GLThread.ListMode = 0;
825
826 unsigned base = ctx->GLThread.ListBase;
827
828 GLbyte *bptr;
829 GLubyte *ubptr;
830 GLshort *sptr;
831 GLushort *usptr;
832 GLint *iptr;
833 GLuint *uiptr;
834 GLfloat *fptr;
835
836 switch (type) {
837 case GL_BYTE:
838 bptr = (GLbyte *) lists;
839 for (unsigned i = 0; i < n; i++)
840 _mesa_glthread_CallList(ctx, base + bptr[i]);
841 break;
842 case GL_UNSIGNED_BYTE:
843 ubptr = (GLubyte *) lists;
844 for (unsigned i = 0; i < n; i++)
845 _mesa_glthread_CallList(ctx, base + ubptr[i]);
846 break;
847 case GL_SHORT:
848 sptr = (GLshort *) lists;
849 for (unsigned i = 0; i < n; i++)
850 _mesa_glthread_CallList(ctx, base + sptr[i]);
851 break;
852 case GL_UNSIGNED_SHORT:
853 usptr = (GLushort *) lists;
854 for (unsigned i = 0; i < n; i++)
855 _mesa_glthread_CallList(ctx, base + usptr[i]);
856 break;
857 case GL_INT:
858 iptr = (GLint *) lists;
859 for (unsigned i = 0; i < n; i++)
860 _mesa_glthread_CallList(ctx, base + iptr[i]);
861 break;
862 case GL_UNSIGNED_INT:
863 uiptr = (GLuint *) lists;
864 for (unsigned i = 0; i < n; i++)
865 _mesa_glthread_CallList(ctx, base + uiptr[i]);
866 break;
867 case GL_FLOAT:
868 fptr = (GLfloat *) lists;
869 for (unsigned i = 0; i < n; i++)
870 _mesa_glthread_CallList(ctx, base + fptr[i]);
871 break;
872 case GL_2_BYTES:
873 ubptr = (GLubyte *) lists;
874 for (unsigned i = 0; i < n; i++) {
875 _mesa_glthread_CallList(ctx, base +
876 (GLint)ubptr[2 * i] * 256 +
877 (GLint)ubptr[2 * i + 1]);
878 }
879 break;
880 case GL_3_BYTES:
881 ubptr = (GLubyte *) lists;
882 for (unsigned i = 0; i < n; i++) {
883 _mesa_glthread_CallList(ctx, base +
884 (GLint)ubptr[3 * i] * 65536 +
885 (GLint)ubptr[3 * i + 1] * 256 +
886 (GLint)ubptr[3 * i + 2]);
887 }
888 break;
889 case GL_4_BYTES:
890 ubptr = (GLubyte *) lists;
891 for (unsigned i = 0; i < n; i++) {
892 _mesa_glthread_CallList(ctx, base +
893 (GLint)ubptr[4 * i] * 16777216 +
894 (GLint)ubptr[4 * i + 1] * 65536 +
895 (GLint)ubptr[4 * i + 2] * 256 +
896 (GLint)ubptr[4 * i + 3]);
897 }
898 break;
899 }
900
901 ctx->GLThread.ListMode = saved_mode;
902 }
903
904 static inline void
_mesa_glthread_NewList(struct gl_context * ctx,GLuint list,GLenum mode)905 _mesa_glthread_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
906 {
907 if (!ctx->GLThread.ListMode)
908 ctx->GLThread.ListMode = MIN2(mode, 0xffff);
909 }
910
911 static inline void
_mesa_glthread_EndList(struct gl_context * ctx)912 _mesa_glthread_EndList(struct gl_context *ctx)
913 {
914 if (!ctx->GLThread.ListMode)
915 return;
916
917 ctx->GLThread.ListMode = 0;
918
919 /* Track the last display list change. */
920 _mesa_glthread_fence_call(ctx, &ctx->GLThread.LastDListChangeBatchIndex);
921 }
922
923 static inline void
_mesa_glthread_DeleteLists(struct gl_context * ctx,GLsizei range)924 _mesa_glthread_DeleteLists(struct gl_context *ctx, GLsizei range)
925 {
926 if (range < 0)
927 return;
928
929 /* Track the last display list change. */
930 _mesa_glthread_fence_call(ctx, &ctx->GLThread.LastDListChangeBatchIndex);
931 }
932
933 static inline void
_mesa_glthread_BindFramebuffer(struct gl_context * ctx,GLenum target,GLuint id)934 _mesa_glthread_BindFramebuffer(struct gl_context *ctx, GLenum target, GLuint id)
935 {
936 switch (target) {
937 case GL_FRAMEBUFFER:
938 ctx->GLThread.CurrentDrawFramebuffer = id;
939 ctx->GLThread.CurrentReadFramebuffer = id;
940 break;
941 case GL_DRAW_FRAMEBUFFER:
942 ctx->GLThread.CurrentDrawFramebuffer = id;
943 break;
944 case GL_READ_FRAMEBUFFER:
945 ctx->GLThread.CurrentReadFramebuffer = id;
946 break;
947 }
948 }
949
950 static inline void
_mesa_glthread_DeleteFramebuffers(struct gl_context * ctx,GLsizei n,const GLuint * ids)951 _mesa_glthread_DeleteFramebuffers(struct gl_context *ctx, GLsizei n,
952 const GLuint *ids)
953 {
954 if (ctx->GLThread.CurrentDrawFramebuffer) {
955 for (int i = 0; i < n; i++) {
956 if (ctx->GLThread.CurrentDrawFramebuffer == ids[i])
957 ctx->GLThread.CurrentDrawFramebuffer = 0;
958 if (ctx->GLThread.CurrentReadFramebuffer == ids[i])
959 ctx->GLThread.CurrentReadFramebuffer = 0;
960 }
961 }
962 }
963
964 #endif /* MARSHAL_H */
965