#include #include #include #include "common/common.h" #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST static int get_glFogfv_params_length(GLenum pname) { return pname == GL_FOG_COLOR ? 4 : 1; } #endif CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(pname, copy_array(get_glFogfv_params_length(pname), params)); #else GLenum pname = args.next(); const GLfloat *params = args.next_arr(); func(pname, params); return 0; #endif } // Track GL State struct gl_array_state_t { bool enabled = false; GLint size = 0; GLenum type = 0; GLsizei stride = 0; uint32_t pointer = 0; bool operator==(const gl_array_state_t &other) const { return enabled == other.enabled && size == other.size && type == other.type && stride == other.stride && pointer == other.pointer; } bool operator!=(const gl_array_state_t &other) const { return !operator==(other); } }; struct gl_state_t { GLuint bound_array_buffer = 0; GLuint bound_texture = 0; gl_array_state_t vertex_array; gl_array_state_t color_array; gl_array_state_t tex_coord_array; // Update State static typeof(glVertexPointer) *get_array_pointer_function(const GLenum array) { switch (array) { case GL_VERTEX_ARRAY: { return glVertexPointer; } case GL_COLOR_ARRAY: { return glColorPointer; } case GL_TEXTURE_COORD_ARRAY: { return glTexCoordPointer; } default: { ERR("Unsupported Array Type: %i", array); } } } gl_array_state_t &get_array_state(const GLenum array) { switch (array) { case GL_VERTEX_ARRAY: { return vertex_array; } case GL_COLOR_ARRAY: { return color_array; } case GL_TEXTURE_COORD_ARRAY: { return tex_coord_array; } default: { ERR("Unsupported Array Function"); } } } #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST void enable_disable_array(const GLenum array, const bool value) { get_array_state(array).enabled = value; } #else void send_array_to_driver(GLenum array) { gl_array_state_t state = get_array_state(array); if (state.enabled) { glEnableClientState(array); } else { glDisableClientState(array); } typeof(glVertexPointer) *func = get_array_pointer_function(array); func(state.size, state.type, state.stride, (const void *) uintptr_t(state.pointer)); } void send_arrays_to_driver() { send_array_to_driver(GL_VERTEX_ARRAY); send_array_to_driver(GL_COLOR_ARRAY); send_array_to_driver(GL_TEXTURE_COORD_ARRAY); } #endif }; #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST static gl_state_t gl_state; #endif // 'pointer' Is Only Supported As An Integer, Not As An Actual Pointer #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #define CALL_GL_POINTER(name, array) \ void name(GLint size, GLenum type, GLsizei stride, const void *pointer) { \ gl_array_state_t &state = gl_state.get_array_state(array); \ state.size = size; \ state.type = type; \ state.stride = stride; \ state.pointer = uint32_t(pointer); \ } #else #define CALL_GL_POINTER(name, array) #endif CALL_GL_POINTER(glVertexPointer, GL_VERTEX_ARRAY) CALL(13, glLineWidth, void, (GLfloat width)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(width); #else func(args.next()); return 0; #endif } CALL(14, glBlendFunc, void, (GLenum sfactor, GLenum dfactor)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(sfactor, dfactor); #else GLenum sfactor = args.next(); GLenum dfactor = args.next(); func(sfactor, dfactor); return 0; #endif } CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(gl_state, mode, first, count); #else gl_state_t gl_state = args.next(); glBindBuffer(GL_ARRAY_BUFFER, gl_state.bound_array_buffer); glBindTexture(GL_TEXTURE_2D, gl_state.bound_texture); gl_state.send_arrays_to_driver(); GLenum mode = args.next(); GLint first = args.next(); GLsizei count = args.next(); func(mode, first, count); return 0; #endif } CALL(16, glColor4f, void, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(red, green, blue, alpha); #else GLfloat red = args.next(); GLfloat green = args.next(); GLfloat blue = args.next(); GLfloat alpha = args.next(); func(red, green, blue, alpha); return 0; #endif } CALL(17, glClear, void, (GLbitfield mask)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(mask); #else func(args.next()); return 0; #endif } CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(gl_state.bound_array_buffer, target, copy_array(size, (unsigned char *) data), usage); #else glBindBuffer(GL_ARRAY_BUFFER, args.next()); GLenum target = args.next(); uint32_t size; const unsigned char *data = args.next_arr(&size); GLenum usage = args.next(); func(target, GLsizeiptr(size), data, usage); return 0; #endif } CALL(19, glFogx, void, (GLenum pname, GLfixed param)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(pname, param); #else GLenum pname = args.next(); GLfixed param = args.next(); func(pname, param); return 0; #endif } CALL(20, glFogf, void, (GLenum pname, GLfloat param)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(pname, param); #else GLenum pname = args.next(); GLfloat param = args.next(); func(pname, param); return 0; #endif } CALL(21, glMatrixMode, void, (GLenum mode)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(mode); #else func(args.next()); return 0; #endif } CALL_GL_POINTER(glColorPointer, GL_COLOR_ARRAY) CALL(23, glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(x, y, width, height); #else GLint x = args.next(); GLint y = args.next(); GLsizei width = args.next(); GLsizei height = args.next(); func(x, y, width, height); return 0; #endif } CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(gl_state.bound_texture, target, pname, param); #else glBindTexture(GL_TEXTURE_2D, args.next()); GLenum target = args.next(); GLenum pname = args.next(); GLint param = args.next(); func(target, pname, param); return 0; #endif } // Get Size (In Memory) Of Specified Texture static int get_texture_size(const GLsizei width, const GLsizei height, const GLenum format, const GLenum type, bool is_upload) { // Calculate Per-Pixel Multiplier int multiplier; if (type == GL_UNSIGNED_BYTE) { switch (format) { case GL_RGB: { multiplier = 3; break; } case GL_RGBA: { multiplier = 4; break; } default: { ERR("Unsupported Texture Format: %u", format); } } } else { // GL_UNSIGNED_SHORT_* multiplier = sizeof(unsigned short); } // Calculate Line Size int line_size = width * multiplier; { // Handle Alignment int alignment; glGetIntegerv(is_upload ? GL_UNPACK_ALIGNMENT : GL_PACK_ALIGNMENT, &alignment); // Round int diff = line_size % alignment; line_size = line_size + (alignment - diff); } // Return return line_size * height; } CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(gl_state.bound_texture, target, level, internalformat, width, height, border, format, type, copy_array(get_texture_size(width, height, format, type, true), (const unsigned char *) pixels)); #else glBindTexture(GL_TEXTURE_2D, args.next()); GLenum target = args.next(); GLint level = args.next(); GLint internalformat = args.next(); GLsizei width = args.next(); GLsizei height = args.next(); GLint border = args.next(); GLenum format = args.next(); GLenum type = args.next(); const unsigned char *pixels = args.next_arr(); func(target, level, internalformat, width, height, border, format, type, pixels); return 0; #endif } CALL(26, glEnable, void, (GLenum cap)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(cap); #else func(args.next()); return 0; #endif } #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST void glEnableClientState(const GLenum array) { gl_state.enable_disable_array(array, true); } #endif CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(factor, units); #else GLfloat factor = args.next(); GLfloat units = args.next(); func(factor, units); return 0; #endif } CALL_GL_POINTER(glTexCoordPointer, GL_TEXTURE_COORD_ARRAY) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST void glDisableClientState(const GLenum array) { gl_state.enable_disable_array(array, false); } #endif CALL(30, glDepthRangef, void, (GLclampf near, GLclampf far)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(near, far); #else GLclampf near = args.next(); GLclampf far = args.next(); func(near, far); return 0; #endif } CALL(31, glDepthFunc, void, (GLenum func)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(func); #else func(args.next()); return 0; #endif } #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST void glBindBuffer(const GLenum target, const GLuint buffer) { if (target == GL_ARRAY_BUFFER) { gl_state.bound_array_buffer = buffer; } else { ERR("Unsupported Buffer Binding: %u", target); } } #endif CALL(33, glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(red, green, blue, alpha); #else GLclampf red = args.next(); GLclampf green = args.next(); GLclampf blue = args.next(); GLclampf alpha = args.next(); func(red, green, blue, alpha); return 0; #endif } CALL(34, glPopMatrix, void, ()) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(); #else func(); return 0; #endif } CALL(35, glLoadIdentity, void, ()) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(); #else func(); return 0; #endif } CALL(36, glScalef, void, (GLfloat x, GLfloat y, GLfloat z)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(x, y, z); #else GLfloat x = args.next(); GLfloat y = args.next(); GLfloat z = args.next(); func(x, y, z); return 0; #endif } CALL(37, glPushMatrix, void, ()) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(); #else func(); return 0; #endif } CALL(38, glDepthMask, void, (GLboolean flag)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(flag); #else func(args.next()); return 0; #endif } CALL(39, glHint, void, (GLenum target, GLenum mode)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(target, mode); #else GLenum target = args.next(); GLenum mode = args.next(); func(target, mode); return 0; #endif } #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST static int get_glMultMatrixf_size() { return 16; } #endif CALL(40, glMultMatrixf, void, (const GLfloat *m)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(copy_array(get_glMultMatrixf_size(), m)); #else func(args.next_arr()); return 0; #endif } CALL(42, glDeleteBuffers, void, (GLsizei n, const GLuint *buffers)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(copy_array(n, buffers)); #else uint32_t n; const GLuint *buffers = args.next_arr(&n); func(GLsizei(n), buffers); return 0; #endif } CALL(43, glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(red, green, blue, alpha); #else GLboolean red = args.next(); GLboolean green = args.next(); GLboolean blue = args.next(); GLboolean alpha = args.next(); func(red, green, blue, alpha); return 0; #endif } CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(gl_state.bound_texture, target, level, xoffset, yoffset, width, height, format, type, copy_array(get_texture_size(width, height, format, type, true), (const unsigned char *) pixels)); #else glBindTexture(GL_TEXTURE_2D, args.next()); GLenum target = args.next(); GLint level = args.next(); GLint xoffset = args.next(); GLint yoffset = args.next(); GLsizei width = args.next(); GLsizei height = args.next(); GLenum format = args.next(); GLenum type = args.next(); const unsigned char *pixels = args.next_arr(); func(target, level, xoffset, yoffset, width, height, format, type, pixels); return 0; #endif } CALL(45, glGenTextures, void, (GLsizei n, GLuint *textures)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(n, uint32_t(textures)); #else GLsizei n = args.next(); GLuint *textures = new GLuint[n]; func(n, textures); writer(args.next(), textures, n * sizeof(GLuint)); delete[] textures; return 0; #endif } CALL(46, glDeleteTextures, void, (GLsizei n, const GLuint *textures)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(copy_array(n, textures)); #else uint32_t n; const GLuint *textures = args.next_arr(&n); func(GLsizei(n), textures); return 0; #endif } CALL(47, glAlphaFunc, void, (GLenum func, GLclampf ref)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(func, ref); #else GLenum func2 = args.next(); GLclampf ref = args.next(); func(func2, ref); return 0; #endif } #ifdef MEDIA_LAYER_TRAMPOLINE_HOST static int get_glGetFloatv_params_size(GLenum pname) { switch (pname) { case GL_MODELVIEW_MATRIX: case GL_PROJECTION_MATRIX: { return 16; } case GL_ALIASED_LINE_WIDTH_RANGE: case GL_SMOOTH_LINE_WIDTH_RANGE: { return 2; } default: { ERR("Unsupported glGetFloatv Property: %u", pname); } } } #endif CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(pname, uint32_t(params)); #else GLenum pname = args.next(); int size = get_glGetFloatv_params_size(pname); GLfloat *params = new GLfloat[size]; func(pname, params); writer(args.next(), params, size * sizeof(GLfloat)); delete[] params; return 0; #endif } #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST void glBindTexture(const GLenum target, const GLuint texture) { if (target == GL_TEXTURE_2D) { gl_state.bound_texture = texture; } else { ERR("Unsupported Texture Binding: %u", target); } } #endif CALL(50, glTranslatef, void, (GLfloat x, GLfloat y, GLfloat z)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(x, y, z); #else GLfloat x = args.next(); GLfloat y = args.next(); GLfloat z = args.next(); func(x, y, z); return 0; #endif } CALL(51, glShadeModel, void, (GLenum mode)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(mode); #else func(args.next()); return 0; #endif } CALL(52, glOrthof, void, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(left, right, bottom, top, near, far); #else GLfloat left = args.next(); GLfloat right = args.next(); GLfloat bottom = args.next(); GLfloat top = args.next(); GLfloat near = args.next(); GLfloat far = args.next(); func(left, right, bottom, top, near, far); return 0; #endif } CALL(53, glDisable, void, (GLenum cap)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(cap); #else func(args.next()); return 0; #endif } CALL(54, glCullFace, void, (GLenum mode)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(mode); #else func(args.next()); return 0; #endif } CALL(55, glRotatef, void, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(angle, x, y, z); #else GLfloat angle = args.next(); GLfloat x = args.next(); GLfloat y = args.next(); GLfloat z = args.next(); func(angle, x, y, z); return 0; #endif } CALL(56, glViewport, void, (GLint x, GLint y, GLsizei width, GLsizei height)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(x, y, width, height); #else GLint x = args.next(); GLint y = args.next(); GLsizei width = args.next(); GLsizei height = args.next(); func(x, y, width, height); return 0; #endif } CALL(57, glNormal3f, void, (GLfloat nx, GLfloat ny, GLfloat nz)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(nx, ny, nz); #else GLfloat nx = args.next(); GLfloat ny = args.next(); GLfloat nz = args.next(); func(nx, ny, nz); return 0; #endif } CALL(58, glIsEnabled, GLboolean, (GLenum cap)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST return trampoline(cap); #else return func(args.next()); #endif } #ifdef MEDIA_LAYER_TRAMPOLINE_HOST static int get_glGetIntegerv_params_size(GLenum pname) { switch (pname) { case GL_TEXTURE_BINDING_2D: case GL_PACK_ALIGNMENT: case GL_UNPACK_ALIGNMENT: { return 1; } case GL_VIEWPORT: { return 4; } default: { ERR("Unsupported glGetIntegerv Property: %u", pname); } } } #endif CALL(61, glGetIntegerv, void, (GLenum pname, GLint *params)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(pname, uint32_t(params)); #else GLenum pname = args.next(); int size = get_glGetIntegerv_params_size(pname); GLint *params = new GLint[size]; func(pname, params); writer(args.next(), params, size * sizeof(GLint)); delete[] params; return 0; #endif } CALL(65, glReadPixels, void, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(x, y, width, height, format, type, uint32_t(data)); #else GLint x = args.next(); GLint y = args.next(); GLsizei width = args.next(); GLsizei height = args.next(); GLenum format = args.next(); GLenum type = args.next(); int data_size = get_texture_size(width, height, format, type, false); unsigned char *data = new unsigned char[data_size]; func(x, y, width, height, format, type, data); writer(args.next(), data, data_size); delete[] data; return 0; #endif } CALL(67, glGenBuffers, void, (GLsizei n, GLuint *buffers)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST trampoline(n, uint32_t(buffers)); #else GLsizei n = args.next(); GLuint *buffers = new GLuint[n]; func(n, buffers); writer(args.next(), buffers, n * sizeof(GLuint)); delete[] buffers; return 0; #endif }