1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2012 Intel Corporation
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21b8e80941Smrg * IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg/** \file marshal.h
25b8e80941Smrg *
26b8e80941Smrg * Declarations of functions related to marshalling GL calls from a client
27b8e80941Smrg * thread to a server thread.
28b8e80941Smrg */
29b8e80941Smrg
30b8e80941Smrg#ifndef MARSHAL_H
31b8e80941Smrg#define MARSHAL_H
32b8e80941Smrg
33b8e80941Smrg#include "main/glthread.h"
34b8e80941Smrg#include "main/context.h"
35b8e80941Smrg#include "main/macros.h"
36b8e80941Smrg
37b8e80941Smrgstruct marshal_cmd_base
38b8e80941Smrg{
39b8e80941Smrg   /**
40b8e80941Smrg    * Type of command.  See enum marshal_dispatch_cmd_id.
41b8e80941Smrg    */
42b8e80941Smrg   uint16_t cmd_id;
43b8e80941Smrg
44b8e80941Smrg   /**
45b8e80941Smrg    * Size of command, in multiples of 4 bytes, including cmd_base.
46b8e80941Smrg    */
47b8e80941Smrg   uint16_t cmd_size;
48b8e80941Smrg};
49b8e80941Smrg
50b8e80941Smrgstatic inline void *
51b8e80941Smrg_mesa_glthread_allocate_command(struct gl_context *ctx,
52b8e80941Smrg                                uint16_t cmd_id,
53b8e80941Smrg                                size_t size)
54b8e80941Smrg{
55b8e80941Smrg   struct glthread_state *glthread = ctx->GLThread;
56b8e80941Smrg   struct glthread_batch *next = &glthread->batches[glthread->next];
57b8e80941Smrg   struct marshal_cmd_base *cmd_base;
58b8e80941Smrg   const size_t aligned_size = ALIGN(size, 8);
59b8e80941Smrg
60b8e80941Smrg   if (unlikely(next->used + size > MARSHAL_MAX_CMD_SIZE)) {
61b8e80941Smrg      _mesa_glthread_flush_batch(ctx);
62b8e80941Smrg      next = &glthread->batches[glthread->next];
63b8e80941Smrg   }
64b8e80941Smrg
65b8e80941Smrg   cmd_base = (struct marshal_cmd_base *)&next->buffer[next->used];
66b8e80941Smrg   next->used += aligned_size;
67b8e80941Smrg   cmd_base->cmd_id = cmd_id;
68b8e80941Smrg   cmd_base->cmd_size = aligned_size;
69b8e80941Smrg   return cmd_base;
70b8e80941Smrg}
71b8e80941Smrg
72b8e80941Smrg/**
73b8e80941Smrg * Instead of conditionally handling marshaling previously-bound user vertex
74b8e80941Smrg * array data in draw calls (deprecated and removed in GL core), we just
75b8e80941Smrg * disable threading at the point where the user sets a user vertex array.
76b8e80941Smrg */
77b8e80941Smrgstatic inline bool
78b8e80941Smrg_mesa_glthread_is_non_vbo_vertex_attrib_pointer(const struct gl_context *ctx)
79b8e80941Smrg{
80b8e80941Smrg   struct glthread_state *glthread = ctx->GLThread;
81b8e80941Smrg
82b8e80941Smrg   return ctx->API != API_OPENGL_CORE && !glthread->vertex_array_is_vbo;
83b8e80941Smrg}
84b8e80941Smrg
85b8e80941Smrg/**
86b8e80941Smrg * Instead of conditionally handling marshaling immediate index data in draw
87b8e80941Smrg * calls (deprecated and removed in GL core), we just disable threading.
88b8e80941Smrg */
89b8e80941Smrgstatic inline bool
90b8e80941Smrg_mesa_glthread_is_non_vbo_draw_elements(const struct gl_context *ctx)
91b8e80941Smrg{
92b8e80941Smrg   struct glthread_state *glthread = ctx->GLThread;
93b8e80941Smrg
94b8e80941Smrg   return ctx->API != API_OPENGL_CORE && !glthread->element_array_is_vbo;
95b8e80941Smrg}
96b8e80941Smrg
97b8e80941Smrg#define DEBUG_MARSHAL_PRINT_CALLS 0
98b8e80941Smrg
99b8e80941Smrg/**
100b8e80941Smrg * This is printed when we have fallen back to a sync. This can happen when
101b8e80941Smrg * MARSHAL_MAX_CMD_SIZE is exceeded.
102b8e80941Smrg */
103b8e80941Smrgstatic inline void
104b8e80941Smrgdebug_print_sync_fallback(const char *func)
105b8e80941Smrg{
106b8e80941Smrg#if DEBUG_MARSHAL_PRINT_CALLS
107b8e80941Smrg   printf("fallback to sync: %s\n", func);
108b8e80941Smrg#endif
109b8e80941Smrg}
110b8e80941Smrg
111b8e80941Smrg
112b8e80941Smrgstatic inline void
113b8e80941Smrgdebug_print_sync(const char *func)
114b8e80941Smrg{
115b8e80941Smrg#if DEBUG_MARSHAL_PRINT_CALLS
116b8e80941Smrg   printf("sync: %s\n", func);
117b8e80941Smrg#endif
118b8e80941Smrg}
119b8e80941Smrg
120b8e80941Smrgstatic inline void
121b8e80941Smrgdebug_print_marshal(const char *func)
122b8e80941Smrg{
123b8e80941Smrg#if DEBUG_MARSHAL_PRINT_CALLS
124b8e80941Smrg   printf("marshal: %s\n", func);
125b8e80941Smrg#endif
126b8e80941Smrg}
127b8e80941Smrg
128b8e80941Smrgstatic inline void
129b8e80941Smrgdebug_print_unmarshal(const char *func)
130b8e80941Smrg{
131b8e80941Smrg#if DEBUG_MARSHAL_PRINT_CALLS
132b8e80941Smrg   printf("unmarshal: %s\n", func);
133b8e80941Smrg#endif
134b8e80941Smrg}
135b8e80941Smrg
136b8e80941Smrgstruct _glapi_table *
137b8e80941Smrg_mesa_create_marshal_table(const struct gl_context *ctx);
138b8e80941Smrg
139b8e80941Smrgsize_t
140b8e80941Smrg_mesa_unmarshal_dispatch_cmd(struct gl_context *ctx, const void *cmd);
141b8e80941Smrg
142b8e80941Smrgstatic inline void
143b8e80941Smrg_mesa_post_marshal_hook(struct gl_context *ctx)
144b8e80941Smrg{
145b8e80941Smrg   /* This can be enabled for debugging whether a failure is a synchronization
146b8e80941Smrg    * problem between the main thread and the worker thread, or a failure in
147b8e80941Smrg    * how we actually marshal.
148b8e80941Smrg    */
149b8e80941Smrg   if (false)
150b8e80941Smrg      _mesa_glthread_finish(ctx);
151b8e80941Smrg}
152b8e80941Smrg
153b8e80941Smrg
154b8e80941Smrg/**
155b8e80941Smrg * Checks whether we're on a compat context for code-generated
156b8e80941Smrg * glBindVertexArray().
157b8e80941Smrg *
158b8e80941Smrg * In order to decide whether a draw call uses only VBOs for vertex and index
159b8e80941Smrg * buffers, we track the current vertex and index buffer bindings by
160b8e80941Smrg * glBindBuffer().  However, the index buffer binding is stored in the vertex
161b8e80941Smrg * array as opposed to the context.  If we were to accurately track whether
162b8e80941Smrg * the index buffer was a user pointer ot not, we'd have to track it per
163b8e80941Smrg * vertex array, which would mean synchronizing with the client thread and
164b8e80941Smrg * looking into the hash table to find the actual vertex array object.  That's
165b8e80941Smrg * more tracking than we'd like to do in the main thread, if possible.
166b8e80941Smrg *
167b8e80941Smrg * Instead, just punt for now and disable threading on apps using vertex
168b8e80941Smrg * arrays and compat contexts.  Apps using vertex arrays can probably use a
169b8e80941Smrg * core context.
170b8e80941Smrg */
171b8e80941Smrgstatic inline bool
172b8e80941Smrg_mesa_glthread_is_compat_bind_vertex_array(const struct gl_context *ctx)
173b8e80941Smrg{
174b8e80941Smrg   return ctx->API != API_OPENGL_CORE;
175b8e80941Smrg}
176b8e80941Smrg
177b8e80941Smrgstruct marshal_cmd_Enable;
178b8e80941Smrgstruct marshal_cmd_ShaderSource;
179b8e80941Smrgstruct marshal_cmd_Flush;
180b8e80941Smrgstruct marshal_cmd_BindBuffer;
181b8e80941Smrgstruct marshal_cmd_BufferData;
182b8e80941Smrgstruct marshal_cmd_BufferSubData;
183b8e80941Smrgstruct marshal_cmd_NamedBufferData;
184b8e80941Smrgstruct marshal_cmd_NamedBufferSubData;
185b8e80941Smrgstruct marshal_cmd_ClearBuffer;
186b8e80941Smrg#define marshal_cmd_ClearBufferfv   marshal_cmd_ClearBuffer
187b8e80941Smrg#define marshal_cmd_ClearBufferiv   marshal_cmd_ClearBuffer
188b8e80941Smrg#define marshal_cmd_ClearBufferuiv  marshal_cmd_ClearBuffer
189b8e80941Smrg#define marshal_cmd_ClearBufferfi   marshal_cmd_ClearBuffer
190b8e80941Smrg
191b8e80941Smrgvoid
192b8e80941Smrg_mesa_unmarshal_Enable(struct gl_context *ctx,
193b8e80941Smrg                       const struct marshal_cmd_Enable *cmd);
194b8e80941Smrg
195b8e80941Smrgvoid GLAPIENTRY
196b8e80941Smrg_mesa_marshal_Enable(GLenum cap);
197b8e80941Smrg
198b8e80941Smrgvoid GLAPIENTRY
199b8e80941Smrg_mesa_marshal_ShaderSource(GLuint shader, GLsizei count,
200b8e80941Smrg                           const GLchar * const *string, const GLint *length);
201b8e80941Smrg
202b8e80941Smrgvoid
203b8e80941Smrg_mesa_unmarshal_ShaderSource(struct gl_context *ctx,
204b8e80941Smrg                             const struct marshal_cmd_ShaderSource *cmd);
205b8e80941Smrg
206b8e80941Smrgvoid GLAPIENTRY
207b8e80941Smrg_mesa_marshal_Flush(void);
208b8e80941Smrg
209b8e80941Smrgvoid
210b8e80941Smrg_mesa_unmarshal_Flush(struct gl_context *ctx,
211b8e80941Smrg                      const struct marshal_cmd_Flush *cmd);
212b8e80941Smrg
213b8e80941Smrgvoid GLAPIENTRY
214b8e80941Smrg_mesa_marshal_BindBuffer(GLenum target, GLuint buffer);
215b8e80941Smrg
216b8e80941Smrgvoid
217b8e80941Smrg_mesa_unmarshal_BindBuffer(struct gl_context *ctx,
218b8e80941Smrg                           const struct marshal_cmd_BindBuffer *cmd);
219b8e80941Smrg
220b8e80941Smrgvoid
221b8e80941Smrg_mesa_unmarshal_BufferData(struct gl_context *ctx,
222b8e80941Smrg                           const struct marshal_cmd_BufferData *cmd);
223b8e80941Smrg
224b8e80941Smrgvoid GLAPIENTRY
225b8e80941Smrg_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data,
226b8e80941Smrg                         GLenum usage);
227b8e80941Smrg
228b8e80941Smrgvoid
229b8e80941Smrg_mesa_unmarshal_BufferSubData(struct gl_context *ctx,
230b8e80941Smrg                              const struct marshal_cmd_BufferSubData *cmd);
231b8e80941Smrg
232b8e80941Smrgvoid GLAPIENTRY
233b8e80941Smrg_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
234b8e80941Smrg                            const GLvoid * data);
235b8e80941Smrg
236b8e80941Smrgvoid
237b8e80941Smrg_mesa_unmarshal_NamedBufferData(struct gl_context *ctx,
238b8e80941Smrg                                const struct marshal_cmd_NamedBufferData *cmd);
239b8e80941Smrg
240b8e80941Smrgvoid GLAPIENTRY
241b8e80941Smrg_mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size,
242b8e80941Smrg                              const GLvoid * data, GLenum usage);
243b8e80941Smrg
244b8e80941Smrgvoid
245b8e80941Smrg_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx,
246b8e80941Smrg                                   const struct marshal_cmd_NamedBufferSubData *cmd);
247b8e80941Smrg
248b8e80941Smrgvoid GLAPIENTRY
249b8e80941Smrg_mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size,
250b8e80941Smrg                                 const GLvoid * data);
251b8e80941Smrg
252b8e80941Smrgvoid
253b8e80941Smrg_mesa_unmarshal_ClearBufferfv(struct gl_context *ctx,
254b8e80941Smrg                              const struct marshal_cmd_ClearBuffer *cmd);
255b8e80941Smrg
256b8e80941Smrgvoid GLAPIENTRY
257b8e80941Smrg_mesa_marshal_ClearBufferfv(GLenum buffer, GLint drawbuffer,
258b8e80941Smrg                            const GLfloat *value);
259b8e80941Smrg
260b8e80941Smrgvoid
261b8e80941Smrg_mesa_unmarshal_ClearBufferiv(struct gl_context *ctx,
262b8e80941Smrg                              const struct marshal_cmd_ClearBuffer *cmd);
263b8e80941Smrg
264b8e80941Smrgvoid GLAPIENTRY
265b8e80941Smrg_mesa_marshal_ClearBufferiv(GLenum buffer, GLint drawbuffer,
266b8e80941Smrg                            const GLint *value);
267b8e80941Smrg
268b8e80941Smrgvoid
269b8e80941Smrg_mesa_unmarshal_ClearBufferuiv(struct gl_context *ctx,
270b8e80941Smrg                               const struct marshal_cmd_ClearBuffer *cmd);
271b8e80941Smrg
272b8e80941Smrgvoid GLAPIENTRY
273b8e80941Smrg_mesa_marshal_ClearBufferuiv(GLenum buffer, GLint drawbuffer,
274b8e80941Smrg                             const GLuint *value);
275b8e80941Smrg
276b8e80941Smrgvoid
277b8e80941Smrg_mesa_unmarshal_ClearBufferfi(struct gl_context *ctx,
278b8e80941Smrg                              const struct marshal_cmd_ClearBuffer *cmd);
279b8e80941Smrg
280b8e80941Smrgvoid GLAPIENTRY
281b8e80941Smrg_mesa_marshal_ClearBufferfi(GLenum buffer, GLint drawbuffer,
282b8e80941Smrg                            const GLfloat depth, const GLint stencil);
283b8e80941Smrg
284b8e80941Smrg#endif /* MARSHAL_H */
285