17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2012 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "glthread_marshal.h" 257ec681f3Smrg#include "dispatch.h" 267ec681f3Smrg#include "uniforms.h" 277ec681f3Smrg 287ec681f3Smrgstruct marshal_cmd_ShaderSource 297ec681f3Smrg{ 307ec681f3Smrg struct marshal_cmd_base cmd_base; 317ec681f3Smrg GLuint shader; 327ec681f3Smrg GLsizei count; 337ec681f3Smrg /* Followed by GLint length[count], then the contents of all strings, 347ec681f3Smrg * concatenated. 357ec681f3Smrg */ 367ec681f3Smrg}; 377ec681f3Smrg 387ec681f3Smrg 397ec681f3Smrguint32_t 407ec681f3Smrg_mesa_unmarshal_ShaderSource(struct gl_context *ctx, 417ec681f3Smrg const struct marshal_cmd_ShaderSource *cmd, 427ec681f3Smrg const uint64_t *last) 437ec681f3Smrg{ 447ec681f3Smrg const GLint *cmd_length = (const GLint *) (cmd + 1); 457ec681f3Smrg const GLchar *cmd_strings = (const GLchar *) (cmd_length + cmd->count); 467ec681f3Smrg /* TODO: how to deal with malloc failure? */ 477ec681f3Smrg const GLchar * *string = malloc(cmd->count * sizeof(const GLchar *)); 487ec681f3Smrg int i; 497ec681f3Smrg 507ec681f3Smrg for (i = 0; i < cmd->count; ++i) { 517ec681f3Smrg string[i] = cmd_strings; 527ec681f3Smrg cmd_strings += cmd_length[i]; 537ec681f3Smrg } 547ec681f3Smrg CALL_ShaderSource(ctx->CurrentServerDispatch, 557ec681f3Smrg (cmd->shader, cmd->count, string, cmd_length)); 567ec681f3Smrg free((void *)string); 577ec681f3Smrg return cmd->cmd_base.cmd_size; 587ec681f3Smrg} 597ec681f3Smrg 607ec681f3Smrg 617ec681f3Smrgstatic size_t 627ec681f3Smrgmeasure_ShaderSource_strings(GLsizei count, const GLchar * const *string, 637ec681f3Smrg const GLint *length_in, GLint *length_out) 647ec681f3Smrg{ 657ec681f3Smrg int i; 667ec681f3Smrg size_t total_string_length = 0; 677ec681f3Smrg 687ec681f3Smrg for (i = 0; i < count; ++i) { 697ec681f3Smrg if (length_in == NULL || length_in[i] < 0) { 707ec681f3Smrg if (string[i]) 717ec681f3Smrg length_out[i] = strlen(string[i]); 727ec681f3Smrg } else { 737ec681f3Smrg length_out[i] = length_in[i]; 747ec681f3Smrg } 757ec681f3Smrg total_string_length += length_out[i]; 767ec681f3Smrg } 777ec681f3Smrg return total_string_length; 787ec681f3Smrg} 797ec681f3Smrg 807ec681f3Smrg 817ec681f3Smrgvoid GLAPIENTRY 827ec681f3Smrg_mesa_marshal_ShaderSource(GLuint shader, GLsizei count, 837ec681f3Smrg const GLchar * const *string, const GLint *length) 847ec681f3Smrg{ 857ec681f3Smrg /* TODO: how to report an error if count < 0? */ 867ec681f3Smrg 877ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 887ec681f3Smrg /* TODO: how to deal with malloc failure? */ 897ec681f3Smrg const size_t fixed_cmd_size = sizeof(struct marshal_cmd_ShaderSource); 907ec681f3Smrg STATIC_ASSERT(sizeof(struct marshal_cmd_ShaderSource) % sizeof(GLint) == 0); 917ec681f3Smrg size_t length_size = count * sizeof(GLint); 927ec681f3Smrg GLint *length_tmp = malloc(length_size); 937ec681f3Smrg size_t total_string_length = 947ec681f3Smrg measure_ShaderSource_strings(count, string, length, length_tmp); 957ec681f3Smrg size_t total_cmd_size = fixed_cmd_size + length_size + total_string_length; 967ec681f3Smrg 977ec681f3Smrg if (total_cmd_size <= MARSHAL_MAX_CMD_SIZE && count > 0) { 987ec681f3Smrg struct marshal_cmd_ShaderSource *cmd = 997ec681f3Smrg _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_ShaderSource, 1007ec681f3Smrg total_cmd_size); 1017ec681f3Smrg GLint *cmd_length = (GLint *) (cmd + 1); 1027ec681f3Smrg GLchar *cmd_strings = (GLchar *) (cmd_length + count); 1037ec681f3Smrg int i; 1047ec681f3Smrg 1057ec681f3Smrg cmd->shader = shader; 1067ec681f3Smrg cmd->count = count; 1077ec681f3Smrg memcpy(cmd_length, length_tmp, length_size); 1087ec681f3Smrg for (i = 0; i < count; ++i) { 1097ec681f3Smrg memcpy(cmd_strings, string[i], cmd_length[i]); 1107ec681f3Smrg cmd_strings += cmd_length[i]; 1117ec681f3Smrg } 1127ec681f3Smrg } else { 1137ec681f3Smrg _mesa_glthread_finish(ctx); 1147ec681f3Smrg CALL_ShaderSource(ctx->CurrentServerDispatch, 1157ec681f3Smrg (shader, count, string, length_tmp)); 1167ec681f3Smrg } 1177ec681f3Smrg free(length_tmp); 1187ec681f3Smrg} 1197ec681f3Smrg 1207ec681f3Smrgvoid 1217ec681f3Smrg_mesa_glthread_ProgramChanged(struct gl_context *ctx) 1227ec681f3Smrg{ 1237ec681f3Smrg struct glthread_state *glthread = &ctx->GLThread; 1247ec681f3Smrg 1257ec681f3Smrg /* Track the last change. */ 1267ec681f3Smrg p_atomic_set(&glthread->LastProgramChangeBatch, glthread->next); 1277ec681f3Smrg _mesa_glthread_flush_batch(ctx); 1287ec681f3Smrg} 1297ec681f3Smrg 1307ec681f3Smrguint32_t 1317ec681f3Smrg_mesa_unmarshal_GetActiveUniform(struct gl_context *ctx, 1327ec681f3Smrg const struct marshal_cmd_GetActiveUniform *cmd, 1337ec681f3Smrg const uint64_t *last) 1347ec681f3Smrg{ 1357ec681f3Smrg unreachable("never executed"); 1367ec681f3Smrg return 0; 1377ec681f3Smrg} 1387ec681f3Smrg 1397ec681f3Smrgstatic void 1407ec681f3Smrgwait_for_glLinkProgram(struct gl_context *ctx) 1417ec681f3Smrg{ 1427ec681f3Smrg /* Wait for the last glLinkProgram call. */ 1437ec681f3Smrg int batch = p_atomic_read(&ctx->GLThread.LastProgramChangeBatch); 1447ec681f3Smrg if (batch != -1) { 1457ec681f3Smrg util_queue_fence_wait(&ctx->GLThread.batches[batch].fence); 1467ec681f3Smrg assert(p_atomic_read(&ctx->GLThread.LastProgramChangeBatch) == -1); 1477ec681f3Smrg } 1487ec681f3Smrg} 1497ec681f3Smrg 1507ec681f3Smrgvoid GLAPIENTRY 1517ec681f3Smrg_mesa_marshal_GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, 1527ec681f3Smrg GLsizei *length, GLint *size, GLenum *type, 1537ec681f3Smrg GLchar * name) 1547ec681f3Smrg{ 1557ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 1567ec681f3Smrg 1577ec681f3Smrg wait_for_glLinkProgram(ctx); 1587ec681f3Smrg 1597ec681f3Smrg /* We can execute glGetActiveUniform without syncing if we are sync'd to 1607ec681f3Smrg * the last calls of glLinkProgram and glDeleteProgram because shader 1617ec681f3Smrg * object IDs and their contents are immutable after those calls and 1627ec681f3Smrg * also thread-safe because they are shared between contexts. 1637ec681f3Smrg * glCreateShaderProgram calls glLinkProgram internally and it always 1647ec681f3Smrg * syncs, so it doesn't need any handling. 1657ec681f3Smrg */ 1667ec681f3Smrg _mesa_GetActiveUniform_impl(program, index, bufSize, length, size, type, 1677ec681f3Smrg name, true); 1687ec681f3Smrg} 1697ec681f3Smrg 1707ec681f3Smrguint32_t 1717ec681f3Smrg_mesa_unmarshal_GetUniformLocation(struct gl_context *ctx, 1727ec681f3Smrg const struct marshal_cmd_GetUniformLocation *cmd, 1737ec681f3Smrg const uint64_t *last) 1747ec681f3Smrg{ 1757ec681f3Smrg unreachable("never executed"); 1767ec681f3Smrg return 0; 1777ec681f3Smrg} 1787ec681f3Smrg 1797ec681f3SmrgGLint GLAPIENTRY 1807ec681f3Smrg_mesa_marshal_GetUniformLocation(GLuint program, const GLchar *name) 1817ec681f3Smrg{ 1827ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 1837ec681f3Smrg 1847ec681f3Smrg wait_for_glLinkProgram(ctx); 1857ec681f3Smrg 1867ec681f3Smrg /* This is thread-safe. See the comment in _mesa_marshal_GetActiveUniform. */ 1877ec681f3Smrg return _mesa_GetUniformLocation_impl(program, name, true); 1887ec681f3Smrg} 189