#include "main/glthread_marshal.h"
#include "main/dispatch.h"
+struct marshal_cmd_CallList
+{
+ struct marshal_cmd_base cmd_base;
+ GLuint num;
+ GLuint list[];
+};
+
uint32_t
_mesa_unmarshal_CallList(struct gl_context *ctx, const struct marshal_cmd_CallList *cmd, const uint64_t *last)
{
- const GLuint list = cmd->list;
- uint64_t *ptr = (uint64_t *) cmd;
- const unsigned cmd_size = align(sizeof(*cmd), 8) / 8;
-
- assert(cmd_size == cmd->cmd_base.cmd_size);
- ptr += cmd_size;
+ const GLuint num = cmd->num;
- if (ptr < last) {
- const struct marshal_cmd_base *next =
- (const struct marshal_cmd_base *)ptr;
+ if (cmd->cmd_base.cmd_size == sizeof(*cmd) / 8) {
+ CALL_CallList(ctx->CurrentServerDispatch, (num));
+ } else {
+ CALL_CallLists(ctx->CurrentServerDispatch, (num, GL_UNSIGNED_INT, cmd->list));
+ }
- /* If the 'next' is also a DISPATCH_CMD_CallList, we transform 'cmd' and 'next' in a CALL_CallLists.
- * If the following commands are also CallList they're including in the CallLists we're building.
- */
- if (next->cmd_id == DISPATCH_CMD_CallList) {
- const int max_list_count = 2048;
- struct marshal_cmd_CallList *next_callist = (struct marshal_cmd_CallList *) next;
- uint32_t *lists = alloca(max_list_count * sizeof(uint32_t));
+ return cmd->cmd_base.cmd_size;
+}
- lists[0] = cmd->list;
- lists[1] = next_callist->list;
+void GLAPIENTRY
+_mesa_marshal_CallList(GLuint list)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct glthread_state *glthread = &ctx->GLThread;
+ struct marshal_cmd_CallList *last = glthread->LastCallList;
- int count = 2;
+ _mesa_glthread_CallList(ctx, list);
- assert(cmd_size == next_callist->cmd_base.cmd_size);
- ptr += cmd_size;
+ /* If the last call is CallList and there is enough space to append another list... */
+ if (last &&
+ (uint64_t*)last + last->cmd_base.cmd_size ==
+ &glthread->next_batch->buffer[glthread->used] &&
+ glthread->used + 1 <= MARSHAL_MAX_CMD_SIZE / 8) {
+ STATIC_ASSERT(sizeof(*last) == 8);
- while (ptr < last && count < max_list_count) {
- next = (const struct marshal_cmd_base *)ptr;
- if (next->cmd_id == DISPATCH_CMD_CallList) {
- next_callist = (struct marshal_cmd_CallList *) next;
- lists[count++] = next_callist->list;
- assert(cmd_size == next_callist->cmd_base.cmd_size);
- ptr += cmd_size;
- } else {
- break;
- }
+ /* Add the list to the last call. */
+ if (last->cmd_base.cmd_size > sizeof(*last) / 8) {
+ last->list[last->num++] = list;
+ if (last->num % 2 == 1) {
+ last->cmd_base.cmd_size++;
+ glthread->used++;
}
-
- CALL_CallLists(ctx->CurrentServerDispatch, (count, GL_UNSIGNED_INT, lists));
-
- return (uint32_t) (ptr - (uint64_t*)cmd);
+ } else {
+ /* Initially, num contains the first list. After we increase cmd_size,
+ * num contains the number of lists and list[] contains the lists.
+ */
+ last->list[0] = last->num;
+ last->list[1] = list;
+ last->num = 2;
+ last->cmd_base.cmd_size++;
+ glthread->used++;
}
+ assert(align(sizeof(*last) + last->num * 4, 8) / 8 == last->cmd_base.cmd_size);
+ return;
}
- CALL_CallList(ctx->CurrentServerDispatch, (list));
- return cmd_size;
-}
-
-void GLAPIENTRY
-_mesa_marshal_CallList(GLuint list)
-{
- GET_CURRENT_CONTEXT(ctx);
int cmd_size = sizeof(struct marshal_cmd_CallList);
struct marshal_cmd_CallList *cmd;
cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_CallList, cmd_size);
- cmd->list = list;
+ cmd->num = list;
- _mesa_glthread_CallList(ctx, list);
+ glthread->LastCallList = cmd;
}