diff --git a/CMakeLists.txt b/CMakeLists.txt index 2385d5f..beda963 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.5.0) -project(sharedgl VERSION 0.7.0 LANGUAGES C) +project(sharedgl VERSION 0.7.1 LANGUAGES C) include_directories(${CMAKE_SOURCE_DIR}/inc) diff --git a/README.md b/README.md index 9d0f013..daa10db 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Variables labeled with `host` get their values from the host/server when their o | GLX_VERSION_OVERRIDE | Digit.Digit | 1.4 | Override the GLX version on the client side. Only available for Linux clients. | | GLSL_VERSION_OVERRIDE | Digit.Digit | | Override the GLSL version on the client side. Available for both Windows and Linux clients. | | SGL_NET_OVER_SHARED | Ip:Port | | If networking is enabled, this environment variable must exist on the guest. Available for both Windows and Linux clients. | -| SGL_RUN_WITH_LOW_PRIORITY | Boolean | true | On older CPUs, by setting the process priority to low / `IDLE_PRIORITY_CLASS`, applications will run smoother as the kernel driver is given more CPU time. This may not be needed on systems with newer CPUs. Only available for Windows clients. | +| SGL_RUN_WITH_LOW_PRIORITY | Boolean | false | On single core setups, by setting the process priority to low / `IDLE_PRIORITY_CLASS`, applications will run smoother as the kernel driver is given more CPU time. Only set to `true` if the VM has only a single VCPU. Only available for Windows clients. | | SGL_WINED3D_DONT_VFLIP | Boolean | false | If running a DirectX application via WineD3D, ensure this variable is set to `true` in order for the application to render the framebuffer in the proper orientation. Only available for Windows clients. | ## Windows (in a VM) @@ -241,8 +241,8 @@ This list describes the amount of functions left from each standard to implement - [x] OpenGL 3 - [x] 3.0 (~84 total) - [x] 3.1 (~15 total) - - [x] 3.2 (~14 remaining) - - [x] 3.3 (~29 remaining) + - [x] 3.2 (~19 total) + - [x] 3.3 (~58 total) - [x] OpenGL 4 - [x] 4.0 (~46 total) - [x] 4.1 (~89 total) diff --git a/inc/client/pb.h b/inc/client/pb.h index 6638a3a..683d1ce 100644 --- a/inc/client/pb.h +++ b/inc/client/pb.h @@ -39,6 +39,9 @@ void pb_write(int s, int c); void pb_copy(void *data, int s, size_t length); void pb_memcpy(const void *src, size_t length); +void pb_memcpy_unaligned(const void *src, size_t length); +void pb_realign(); + void *pb_ptr(size_t offs); /* diff --git a/inc/sharedgl.h b/inc/sharedgl.h index 482351c..80a29b9 100644 --- a/inc/sharedgl.h +++ b/inc/sharedgl.h @@ -35,7 +35,7 @@ #define SGL_OFFSET_REGISTER_CLAIM_ID (sizeof(int) * 4) #define SGL_OFFSET_REGISTER_CONNECT (sizeof(int) * 5) #define SGL_OFFSET_REGISTER_FBSTART (sizeof(int) * 6) -#define SGL_OFFSET_REGISTER_MEMSIZE (sizeof(int) * 10) +#define SGL_OFFSET_REGISTER_MEMSIZE (sizeof(int) * 8) #define SGL_OFFSET_REGISTER_GLMAJ (sizeof(int) * 11) #define SGL_OFFSET_REGISTER_GLMIN (sizeof(int) * 12) #define SGL_OFFSET_REGISTER_RETVAL_V (sizeof(int) * 13) @@ -64,7 +64,7 @@ # define FORCEINLINE __attribute__((always_inline)) #endif -inline bool is_value_likely_an_offset(const void *p) +static inline bool is_value_likely_an_offset(const void *p) { uintptr_t v = (uintptr_t)p; return v < 0x100000; diff --git a/src/client/glimpl.c b/src/client/glimpl.c index 8669bd4..314efe2 100644 --- a/src/client/glimpl.c +++ b/src/client/glimpl.c @@ -540,7 +540,7 @@ void *glimpl_fb_address() /* fake framebuffer used with network feature only */ if (fake_framebuffer) return fake_framebuffer; - return pb_ptr(pb_read(SGL_OFFSET_REGISTER_FBSTART)); + return pb_ptr(pb_read64(SGL_OFFSET_REGISTER_FBSTART)); } void glimpl_init() @@ -683,6 +683,33 @@ static inline size_t glimpl_get_pixel_size(GLenum format) } } +static inline size_t glimpl_type_size(GLenum type) +{ + switch(type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return sizeof(GLbyte); + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return sizeof(GLshort); + case GL_INT_2_10_10_10_REV: + case GL_INT: + case GL_UNSIGNED_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_DOUBLE: + return sizeof(GLdouble); + case GL_FIXED: + return sizeof(GLfixed); + case GL_HALF_FLOAT: + return sizeof(GLshort); + } + + return 1; +} + static inline void glimpl_upload_buffer(const void *data, size_t size) { pb_push(SGL_CMD_VP_UPLOAD); @@ -723,75 +750,59 @@ static void glimpl_upload_texture(GLsizei width, GLsizei height, GLsizei depth, glimpl_upload_buffer(pixels, total_size); } -static inline void glimpl_push_client_pointers(int mode, int max_index) +static inline bool glimpl_push_client_pointer(int count, int size, int type, int stride, const void *pointer) { - if (glimpl_normal_ptr.in_use) { - pb_push(SGL_CMD_VP_UPLOAD); - pb_push(max_index * glimpl_vertex_ptr.size); - const float *fvertices = glimpl_normal_ptr.pointer; - - for (int i = 0; i < max_index; i++) { - for (int j = 0; j < glimpl_vertex_ptr.size; j++) - pb_pushf(*fvertices++); - for (int j = 0; j < (glimpl_normal_ptr.stride / sizeof(float)) - glimpl_vertex_ptr.size; j++) - fvertices++; + const unsigned char *data = pointer; + size_t sizeof_type = glimpl_type_size(type); + + if (is_value_likely_an_offset(pointer)) + return false; + + pb_push(SGL_CMD_VP_UPLOAD); + pb_push((count * size) / CEIL_DIV(sizeof(int), sizeof_type)); + + if (stride == 0) + pb_memcpy(data, count * size * sizeof_type); + else { + for (int i = 0; i < count; i++) { + void *real_data = ((char*)data + i * stride); + pb_memcpy_unaligned(real_data, size * sizeof_type); } + pb_realign(); + } + + return true; +} + +static inline void glimpl_push_client_pointers(int mode, int count) +{ + if (glimpl_normal_ptr.in_use) { + bool status = glimpl_push_client_pointer(count, glimpl_vertex_ptr.size, + glimpl_normal_ptr.type, glimpl_normal_ptr.stride, glimpl_normal_ptr.pointer); pb_push(SGL_CMD_NORMALPOINTER); pb_push(glimpl_normal_ptr.type); pb_push(0); + pb_push(status); + pb_push(status ? 0 : (int)(uintptr_t)glimpl_normal_ptr.pointer); } if (glimpl_color_ptr.in_use) { - pb_push(SGL_CMD_VP_UPLOAD); - pb_push(max_index); - const unsigned char *color = glimpl_color_ptr.pointer; - for (int i = 0; i < max_index; i++) { - pb_push(*(unsigned int*)color); - color += (glimpl_color_ptr.stride); - } + bool status = glimpl_push_client_pointer(count, glimpl_color_ptr.size, + glimpl_color_ptr.type, glimpl_color_ptr.stride, glimpl_color_ptr.pointer); pb_push(SGL_CMD_COLORPOINTER); pb_push(glimpl_color_ptr.size); pb_push(glimpl_color_ptr.type); pb_push(0); + pb_push(status); + pb_push(status ? 0 : (int)(uintptr_t)glimpl_color_ptr.pointer); } for (int t = 0; t < GLIMPL_MAX_TEXTURES; t++) { if (glimpl_tex_coord_ptr[t].in_use) { - switch (glimpl_tex_coord_ptr[t].type) { - case GL_SHORT: { - pb_push(SGL_CMD_VP_UPLOAD); - pb_push(max_index * glimpl_tex_coord_ptr[t].size / 2); - - const short *svertices = glimpl_tex_coord_ptr[t].pointer; - - // assuming size = 2 - for (int i = 0; i < max_index; i++) { - for (int j = 0; j < glimpl_tex_coord_ptr[t].size; j += 2) { - pb_push((svertices[0] << 16) | svertices[1]); - svertices++; - svertices++; - } - for (int j = 0; j < (glimpl_tex_coord_ptr[t].stride / sizeof(short)) - glimpl_tex_coord_ptr[t].size; j++) - svertices++; - // svertices += glimpl_tex_coord_ptr[t].stride / sizeof(short); - } - } - default: { - pb_push(SGL_CMD_VP_UPLOAD); - pb_push(max_index * glimpl_tex_coord_ptr[t].size); - - const float *fvertices = glimpl_tex_coord_ptr[t].pointer; - - for (int i = 0; i < max_index; i++) { - for (int j = 0; j < glimpl_tex_coord_ptr[t].size; j++) - pb_pushf(*fvertices++); - for (int j = 0; j < (glimpl_tex_coord_ptr[t].stride / sizeof(float)) - glimpl_tex_coord_ptr[t].size; j++) - fvertices++; - } - } - } + bool status = glimpl_push_client_pointer(count, glimpl_tex_coord_ptr[t].size, + glimpl_tex_coord_ptr[t].type, glimpl_tex_coord_ptr[t].stride, glimpl_tex_coord_ptr[t].pointer); pb_push(SGL_CMD_CLIENTACTIVETEXTURE); pb_push(GL_TEXTURE0 + t); @@ -803,25 +814,21 @@ static inline void glimpl_push_client_pointers(int mode, int max_index) pb_push(glimpl_tex_coord_ptr[t].size); pb_push(glimpl_tex_coord_ptr[t].type); pb_push(0); + pb_push(status); + pb_push(status ? 0 : (int)(uintptr_t)glimpl_tex_coord_ptr[t].pointer); } } if (glimpl_vertex_ptr.in_use) { - pb_push(SGL_CMD_VP_UPLOAD); - pb_push(max_index * glimpl_vertex_ptr.size); - const float *fvertices = glimpl_vertex_ptr.pointer; - - for (int i = 0; i < max_index; i++) { - for (int j = 0; j < glimpl_vertex_ptr.size; j++) - pb_pushf(*fvertices++); - for (int j = 0; j < (glimpl_vertex_ptr.stride / sizeof(float)) - glimpl_vertex_ptr.size; j++) - fvertices++; - } + bool status = glimpl_push_client_pointer(count, glimpl_vertex_ptr.size, + glimpl_vertex_ptr.type, glimpl_vertex_ptr.stride, glimpl_vertex_ptr.pointer); pb_push(SGL_CMD_VERTEXPOINTER); pb_push(glimpl_vertex_ptr.size); pb_push(glimpl_vertex_ptr.type); pb_push(0); + pb_push(status); + pb_push(status ? 0 : (int)(uintptr_t)glimpl_vertex_ptr.pointer); } } @@ -1352,8 +1359,7 @@ void glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_grou void glDrawArrays(GLenum mode, GLint first, GLsizei count) { - struct gl_vertex_attrib_pointer *vap = glimpl_get_enabled_vap(); - + // struct gl_vertex_attrib_pointer *vap = glimpl_get_enabled_vap(); // if (vap) { // if (vap->client_managed) { // if (!is_value_likely_an_offset(vap->ptr)) { diff --git a/src/client/pb.c b/src/client/pb.c index b998e64..f243b05 100644 --- a/src/client/pb.c +++ b/src/client/pb.c @@ -59,7 +59,7 @@ void pb_set(int fd) { ptr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - int alloc_size = *(int*)(ptr + SGL_OFFSET_REGISTER_MEMSIZE); + uintptr_t alloc_size = *(uintptr_t*)(ptr + SGL_OFFSET_REGISTER_MEMSIZE); munmap(ptr, 0x1000); ptr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); @@ -195,6 +195,23 @@ void pb_memcpy(const void *src, size_t length) in_cur += CEIL_DIV(length, 4); } +void pb_memcpy_unaligned(const void *src, size_t length) +{ + // length = length - (length % 4); + memcpy(in_cur, src, length); + in_cur = (int*)((char*)in_cur + length); +} + +static inline uintptr_t align_to_4(uintptr_t ptr) +{ + return (ptr + 3) & ~3; +} + +void pb_realign() +{ + in_cur = (int*)align_to_4((uintptr_t)in_cur); +} + void *pb_ptr(size_t offs) { if (net_hooks._pb_ptr) diff --git a/src/client/winmain.c b/src/client/winmain.c index baf175b..24d51f2 100644 --- a/src/client/winmain.c +++ b/src/client/winmain.c @@ -16,10 +16,10 @@ BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) * more CPU time, which is crucial because the kernel driver is how data * between the VM and host move. * - * appears to benefit systems with a single core the most + * appears to benefit systems with a single VCPU the most */ DWORD result = GetEnvironmentVariableA("SGL_RUN_WITH_LOW_PRIORITY", env_value, 16); - if (result == 0 || strcmp(env_value, "true") == 0) + if (strcmp(env_value, "true") == 0) SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); /* diff --git a/src/server/processor.c b/src/server/processor.c index d92f3ea..b67dbd0 100644 --- a/src/server/processor.c +++ b/src/server/processor.c @@ -132,15 +132,15 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args) struct net_context *net_ctx = NULL; - if ((signed)fifo_size < 0) { + if ((intptr_t)fifo_size < 0) { PRINT_LOG("framebuffer too big, try increasing memory!\n"); return; } memset(p + SGL_OFFSET_COMMAND_START, 0, fifo_size); - *(int*)(p + SGL_OFFSET_REGISTER_FBSTART) = SGL_OFFSET_COMMAND_START + fifo_size; - *(int*)(p + SGL_OFFSET_REGISTER_MEMSIZE) = args.memory_size; + *(uint64_t*)(p + SGL_OFFSET_REGISTER_FBSTART) = SGL_OFFSET_COMMAND_START + fifo_size; + *(uint64_t*)(p + SGL_OFFSET_REGISTER_MEMSIZE) = args.memory_size; *(int*)(p + SGL_OFFSET_REGISTER_GLMAJ) = args.gl_major; *(int*)(p + SGL_OFFSET_REGISTER_GLMIN) = args.gl_minor; *(int*)(p + SGL_OFFSET_REGISTER_CONNECT) = 0; @@ -917,31 +917,39 @@ void sgl_cmd_processor_start(struct sgl_cmd_processor_args args) case SGL_CMD_COLORPOINTER: { int size = *pb++, type = *pb++, - stride = *pb++; - glColorPointer(size, type, stride, uploaded); + stride = *pb++, + use_upload = *pb++, + offs = *pb++; + glColorPointer(size, type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs); //// printf("glColorPointer(0x%x, 0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", size, type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]); break; } case SGL_CMD_NORMALPOINTER: { int type = *pb++, - stride = *pb++; - glNormalPointer(type, stride, uploaded); + stride = *pb++, + use_upload = *pb++, + offs = *pb++; + glNormalPointer(type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs); //// printf("glNormalPointer(0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]); break; } case SGL_CMD_TEXCOORDPOINTER: { int size = *pb++, type = *pb++, - stride = *pb++; - glTexCoordPointer(size, type, stride, uploaded); + stride = *pb++, + use_upload = *pb++, + offs = *pb++; + glTexCoordPointer(size, type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs); //// printf("glTexCoordPointer(0x%x, 0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", size, type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]); break; } case SGL_CMD_VERTEXPOINTER: { int size = *pb++, type = *pb++, - stride = *pb++; - glVertexPointer(size, type, stride, uploaded); + stride = *pb++, + use_upload = *pb++, + offs = *pb++; + glVertexPointer(size, type, stride, use_upload ? uploaded : (const void*)(uintptr_t)offs); //// printf("glVertexPointer(0x%x, 0x%x, %d, [%f, %f, %f, %f, %f, %f, ...]);\n", size, type, stride, ((float*)uploaded)[0], ((float*)uploaded)[1], ((float*)uploaded)[2], ((float*)uploaded)[3], ((float*)uploaded)[4], ((float*)uploaded)[5]); break; }