diff --git a/Sources/httprequest.cpp b/Sources/httprequest.cpp index 250b4bc..1bd59bf 100644 --- a/Sources/httprequest.cpp +++ b/Sources/httprequest.cpp @@ -2361,7 +2361,17 @@ static void XMLHttpRequestGetResponseHeader(const FunctionCallbackInfo& a } } -void createXMLHttpRequestClass(Isolate* isolate, Local& global) { +void bind_httprequest_class(Isolate* isolate, const Global& context) { + HttpRequestWrapper::initialize(); + + Locker locker{isolate}; + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + Local current_context = Local::New(isolate, context); + Context::Scope context_scope(current_context); + Local global = current_context->Global(); + Local xhrTpl = FunctionTemplate::New(isolate, XMLHttpRequestConstructor); xhrTpl->SetClassName(String::NewFromUtf8(isolate, "XMLHttpRequest").ToLocalChecked()); xhrTpl->InstanceTemplate()->SetInternalFieldCount(1); @@ -2374,14 +2384,14 @@ void createXMLHttpRequestClass(Isolate* isolate, Local& global) proto->Set(isolate, "getAllResponseHeaders", FunctionTemplate::New(isolate, XMLHttpRequestGetAllResponseHeaders)); proto->Set(isolate, "getResponseHeader", FunctionTemplate::New(isolate, XMLHttpRequestGetResponseHeader)); - Local xhrFunc = xhrTpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked(); - xhrFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "UNSENT").ToLocalChecked(), Integer::New(isolate, 0)); - xhrFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "OPENED").ToLocalChecked(), Integer::New(isolate, 1)); - xhrFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "HEADERS_RECEIVED").ToLocalChecked(), Integer::New(isolate, 2)); - xhrFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "LOADING").ToLocalChecked(), Integer::New(isolate, 3)); - xhrFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "DONE").ToLocalChecked(), Integer::New(isolate, 4)); + Local xhrFunc = xhrTpl->GetFunction(current_context).ToLocalChecked(); + xhrFunc->Set(current_context, String::NewFromUtf8(isolate, "UNSENT").ToLocalChecked(), Integer::New(isolate, 0)); + xhrFunc->Set(current_context, String::NewFromUtf8(isolate, "OPENED").ToLocalChecked(), Integer::New(isolate, 1)); + xhrFunc->Set(current_context, String::NewFromUtf8(isolate, "HEADERS_RECEIVED").ToLocalChecked(), Integer::New(isolate, 2)); + xhrFunc->Set(current_context, String::NewFromUtf8(isolate, "LOADING").ToLocalChecked(), Integer::New(isolate, 3)); + xhrFunc->Set(current_context, String::NewFromUtf8(isolate, "DONE").ToLocalChecked(), Integer::New(isolate, 4)); - global->Set(isolate, "XMLHttpRequest", xhrTpl); + global->Set(current_context, String::NewFromUtf8(isolate, "XMLHttpRequest").ToLocalChecked(), xhrFunc); } #endif \ No newline at end of file diff --git a/Sources/httprequest.h b/Sources/httprequest.h index e499f59..cd727ab 100644 --- a/Sources/httprequest.h +++ b/Sources/httprequest.h @@ -230,6 +230,6 @@ void runt_httprequest_set_onprogress(const v8::FunctionCallbackInfo& void runt_httprequest_set_onloadstart(const v8::FunctionCallbackInfo& args); void runt_httprequest_set_onloadend(const v8::FunctionCallbackInfo& args); -void createXMLHttpRequestClass(v8::Isolate* isolate, v8::Local& global); +void bind_httprequest_class(v8::Isolate* isolate, const v8::Global& context); #endif \ No newline at end of file diff --git a/Sources/main.cpp b/Sources/main.cpp index 159ede3..809df8e 100644 --- a/Sources/main.cpp +++ b/Sources/main.cpp @@ -3054,13 +3054,6 @@ namespace { } } - #ifdef WITH_NETWORKING - WebSocketWrapper::initialize(); - //kinc_log(KINC_LOG_LEVEL_INFO, "WebSocket client support initialized successfully"); - HttpRequestWrapper::initialize(); - //kinc_log(KINC_LOG_LEVEL_INFO, "Initializing native HTTP request support"); - #endif - } void start_runt(char *scriptfile) { @@ -4037,11 +4030,9 @@ int kickstart(int argc, char **argv) { #ifdef WITH_WORKER bind_worker_class(isolate, global_context); #endif - #ifdef WITH_NETWORKING - //#ifndef WITH_UWS - //bind_socket_bridge(isolate, global_context); - //#endif + bind_websocket_class(isolate, global_context); + bind_httprequest_class(isolate, global_context); WEBSOCKET_BIND_V8(isolate, global_context); #endif diff --git a/Sources/viewport_server.cpp b/Sources/viewport_server.cpp index 7f67e58..f2ed445 100644 --- a/Sources/viewport_server.cpp +++ b/Sources/viewport_server.cpp @@ -1,6 +1,6 @@ /** * Viewport Server Implementation - Shared Memory Framebuffer Export - * + * */ #include "viewport_server.h" @@ -12,7 +12,11 @@ #include #include -#ifdef KINC_WINDOWS +#ifdef KINC_OPENGL +#include +#endif + +#ifdef KINC_DIRECT3D11 #include #include @@ -254,6 +258,8 @@ bool viewport_server_init(const char* shmem_name, int width, int height) { uint8_t* pixel_dest = (uint8_t*)g_viewport_state.shmem_ptr + VIEWPORT_HEADER_SIZE; memset(pixel_dest, 0, max_pixel_size); +#if !defined(KINC_DIRECT3D11) && !defined(KINC_OPENGL) + // Only create render target for platforms that need it (not Direct3D11 or OpenGL) kinc_g4_render_target_t* rt = (kinc_g4_render_target_t*)malloc(sizeof(kinc_g4_render_target_t)); if (!rt) { kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to allocate render target"); @@ -264,6 +270,7 @@ bool viewport_server_init(const char* shmem_name, int width, int height) { kinc_g4_render_target_init(rt, width, height, KINC_G4_RENDER_TARGET_FORMAT_32BIT, 24, 0); g_viewport_state.render_target = rt; +#endif g_viewport_state.enabled = true; g_viewport_state.initialized = true; @@ -275,7 +282,7 @@ bool viewport_server_init(const char* shmem_name, int width, int height) { return true; } -#ifdef KINC_WINDOWS +#ifdef KINC_DIRECT3D11 static ID3D11Texture2D* g_stagingTexture = NULL; static int g_stagingWidth = 0, g_stagingHeight = 0; #endif @@ -285,7 +292,7 @@ void viewport_server_shutdown(void) { return; } -#ifdef KINC_WINDOWS +#ifdef KINC_DIRECT3D11 if (g_stagingTexture) { g_stagingTexture->Release(); g_stagingTexture = NULL; @@ -294,11 +301,13 @@ void viewport_server_shutdown(void) { } #endif +#if !defined(KINC_DIRECT3D11) && !defined(KINC_OPENGL) if (g_viewport_state.render_target) { kinc_g4_render_target_destroy((kinc_g4_render_target_t*)g_viewport_state.render_target); free(g_viewport_state.render_target); g_viewport_state.render_target = NULL; } +#endif if (g_viewport_state.pixel_buffer) { free(g_viewport_state.pixel_buffer); @@ -346,7 +355,7 @@ void viewport_server_end_frame(void) { uint8_t* pixels = g_viewport_state.pixel_buffer; uint8_t* pixel_dest = (uint8_t*)g_viewport_state.shmem_ptr + VIEWPORT_HEADER_SIZE; -#ifdef KINC_WINDOWS +#ifdef KINC_DIRECT3D11 // Direct3D11 - read from backbuffer BEFORE swap_buffers ID3D11DeviceContext* context = dx_ctx.context; ID3D11Device* device = dx_ctx.device; @@ -417,20 +426,33 @@ void viewport_server_end_frame(void) { memcpy(pixel_dest, pixels, pixel_size); } } +#elif defined(KINC_OPENGL) + // OpenGL - read from default framebuffer using glReadPixels + glReadPixels(0, 0, g_viewport_state.width, g_viewport_state.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + // OpenGL returns pixels bottom-to-top, need to flip + size_t row_size = g_viewport_state.width * 4; + for (int y = 0; y < g_viewport_state.height / 2; ++y) { + uint8_t* row_top = pixels + y * row_size; + uint8_t* row_bottom = pixels + (g_viewport_state.height - 1 - y) * row_size; + for (size_t x = 0; x < row_size; ++x) { + uint8_t temp = row_top[x]; + row_top[x] = row_bottom[x]; + row_bottom[x] = temp; + } + } + memcpy(pixel_dest, pixels, pixel_size); #else // other platforms use render target - if (g_viewport_state.render_target) { - kinc_g4_render_target_t* rt = (kinc_g4_render_target_t*)g_viewport_state.render_target; - kinc_g4_render_target_get_pixels(rt, pixels); - memcpy(pixel_dest, pixels, pixel_size); - } + kinc_g4_render_target_t* rt = (kinc_g4_render_target_t*)g_viewport_state.render_target; + kinc_g4_render_target_get_pixels(rt, pixels); + memcpy(pixel_dest, pixels, pixel_size); #endif g_viewport_state.frame_count++; header->frame_id = g_viewport_state.frame_count; - // NOTE: Camera sync from RunT to Blender is handled via viewport_server_set_camera() - // which is called explicitly when RunT's internal camera changes. + // NOTE: Camera sync from Krom to Blender is handled via viewport_server_set_camera() + // which is called explicitly when Krom's internal camera changes. // We do NOT extract camera from view_matrix here as that would create a feedback loop // (Blender sends view_matrix -> we extract camera -> Blender applies it -> repeat) @@ -478,19 +500,23 @@ bool viewport_server_resize(int new_width, int new_height) { // resize the actual Kinc window so the D3D11 backbuffer is the correct size critical because viewport_server_end_frame captures from the backbuffer kinc_window_resize(0, new_width, new_height); +#if !defined(KINC_DIRECT3D11) && !defined(KINC_OPENGL) if (g_viewport_state.render_target) { kinc_g4_render_target_destroy((kinc_g4_render_target_t*)g_viewport_state.render_target); // dont free here we reuse the allocation } +#endif // update dimensions pre-allocated and reinitialize render target with new size using same memory g_viewport_state.width = new_width; g_viewport_state.height = new_height; +#if !defined(KINC_DIRECT3D11) && !defined(KINC_OPENGL) kinc_g4_render_target_t* rt = (kinc_g4_render_target_t*)g_viewport_state.render_target; if (rt) { kinc_g4_render_target_init(rt, new_width, new_height, KINC_G4_RENDER_TARGET_FORMAT_32BIT, 24, 0); } +#endif SharedFramebufferHeader* header = (SharedFramebufferHeader*)g_viewport_state.shmem_ptr; if (header) { @@ -537,16 +563,16 @@ void viewport_server_set_camera(float pos_x, float pos_y, float pos_z, SharedFramebufferHeader* header = (SharedFramebufferHeader*)g_viewport_state.shmem_ptr; if (!header) return; - header->runt_camera_pos[0] = pos_x; - header->runt_camera_pos[1] = pos_y; - header->runt_camera_pos[2] = pos_z; + header->krom_camera_pos[0] = pos_x; + header->krom_camera_pos[1] = pos_y; + header->krom_camera_pos[2] = pos_z; - header->runt_camera_rot[0] = rot_x; - header->runt_camera_rot[1] = rot_y; - header->runt_camera_rot[2] = rot_z; - header->runt_camera_rot[3] = rot_w; + header->krom_camera_rot[0] = rot_x; + header->krom_camera_rot[1] = rot_y; + header->krom_camera_rot[2] = rot_z; + header->krom_camera_rot[3] = rot_w; - header->runt_camera_dirty = 1; + header->krom_camera_dirty = 1; } bool viewport_server_read_input(InputEvent* event) { @@ -572,9 +598,9 @@ bool viewport_server_read_input(InputEvent* event) { bool viewport_server_input_enabled(void) { if (!viewport_server_is_enabled()) return false; - + SharedFramebufferHeader* header = (SharedFramebufferHeader*)g_viewport_state.shmem_ptr; if (!header) return false; - + return header->input_enabled != 0; } diff --git a/Sources/websocket.cpp b/Sources/websocket.cpp index a817fe6..62c33b3 100644 --- a/Sources/websocket.cpp +++ b/Sources/websocket.cpp @@ -2766,24 +2766,6 @@ static void WebSocketClose(const FunctionCallbackInfo& args) { } } -void createWebSocketClass(Isolate* isolate, Local& global) { - Local wsTpl = FunctionTemplate::New(isolate, WebSocketConstructor); - wsTpl->SetClassName(String::NewFromUtf8(isolate, "WebSocket").ToLocalChecked()); - wsTpl->InstanceTemplate()->SetInternalFieldCount(1); - - Local proto = wsTpl->PrototypeTemplate(); - proto->Set(isolate, "send", FunctionTemplate::New(isolate, WebSocketSend)); - proto->Set(isolate, "close", FunctionTemplate::New(isolate, WebSocketClose)); - - Local wsFunc = wsTpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked(); - wsFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "CONNECTING").ToLocalChecked(), Integer::New(isolate, 0)); - wsFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "OPEN").ToLocalChecked(), Integer::New(isolate, 1)); - wsFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "CLOSING").ToLocalChecked(), Integer::New(isolate, 2)); - wsFunc->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "CLOSED").ToLocalChecked(), Integer::New(isolate, 3)); - - global->Set(isolate, "WebSocket", wsTpl); -} - static void EventConstructor(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); @@ -2887,4 +2869,32 @@ void createWebSocketEventClasses(Isolate* isolate, Local& global global->Set(isolate, "CloseEvent", closeEventTpl); } +void bind_websocket_class(Isolate* isolate, const Global& context) { + WebSocketWrapper::initialize(); + + Locker locker{isolate}; + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + Local current_context = Local::New(isolate, context); + Context::Scope context_scope(current_context); + Local global = current_context->Global(); + + Local wsTpl = FunctionTemplate::New(isolate, WebSocketConstructor); + wsTpl->SetClassName(String::NewFromUtf8(isolate, "WebSocket").ToLocalChecked()); + wsTpl->InstanceTemplate()->SetInternalFieldCount(1); + + Local proto = wsTpl->PrototypeTemplate(); + proto->Set(isolate, "send", FunctionTemplate::New(isolate, WebSocketSend)); + proto->Set(isolate, "close", FunctionTemplate::New(isolate, WebSocketClose)); + + Local wsFunc = wsTpl->GetFunction(current_context).ToLocalChecked(); + wsFunc->Set(current_context, String::NewFromUtf8(isolate, "CONNECTING").ToLocalChecked(), Integer::New(isolate, 0)); + wsFunc->Set(current_context, String::NewFromUtf8(isolate, "OPEN").ToLocalChecked(), Integer::New(isolate, 1)); + wsFunc->Set(current_context, String::NewFromUtf8(isolate, "CLOSING").ToLocalChecked(), Integer::New(isolate, 2)); + wsFunc->Set(current_context, String::NewFromUtf8(isolate, "CLOSED").ToLocalChecked(), Integer::New(isolate, 3)); + + global->Set(current_context, String::NewFromUtf8(isolate, "WebSocket").ToLocalChecked(), wsFunc); +} + #endif diff --git a/Sources/websocket.h b/Sources/websocket.h index 6aced00..e810c5c 100644 --- a/Sources/websocket.h +++ b/Sources/websocket.h @@ -201,6 +201,6 @@ void runt_websocket_set_onmessage(const v8::FunctionCallbackInfo& arg void runt_websocket_set_onerror(const v8::FunctionCallbackInfo& args); void runt_websocket_set_onclose(const v8::FunctionCallbackInfo& args); -void createWebSocketClass(v8::Isolate* isolate, v8::Local& global); +void bind_websocket_class(v8::Isolate* isolate, const v8::Global& context); void createWebSocketEventClasses(v8::Isolate* isolate, v8::Local& global); #endif \ No newline at end of file