Ejemplo n.º 1
0
bool is_gui_aligned(GLFWwindow *win)
{
#ifdef _WIN32
    try
    {
        auto hwn = glfwGetWin32Window(win);
        if (hwn == nullptr)
            return true;

        auto flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
            ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar |
            ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBringToFrontOnFocus;

        ImGui::SetNextWindowPos({ 0, 0 });

        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
        ImGui::Begin("is_gui_aligned", nullptr, flags);

        auto DrawList = ImGui::GetWindowDrawList();
        if (DrawList == nullptr)
            return true;

        DrawList->AddRectFilled({ 0,0 }, { 1,1 }, ImColor(MAGIC / 255.f, 0.f, 0.f, 1.f));

        ImGui::End();
        ImGui::PopStyleVar();

        ImGui::Render();

        glfwSwapBuffers(win);

        ImGui_ImplGlfw_NewFrame(1.f);

        SetFocus(hwn);

        int width = 1;
        int height = 1;

        HDC hdc = GetDC(hwn);
        if (hdc == nullptr)
            return true;

        std::shared_ptr<HDC> shared_hdc(&hdc, [&](HDC* hdc) {ReleaseDC(hwn, *hdc); DeleteDC(*hdc);});

        HDC hCaptureDC = CreateCompatibleDC(hdc);
        if (hCaptureDC == nullptr)
            return true;

        std::shared_ptr<HDC> shared_capture_hdc(&hCaptureDC, [&](HDC* hdc) {ReleaseDC(hwn, *hdc); DeleteDC(*hdc);});

        HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hdc, width, height);
        if (hCaptureBitmap == nullptr)
            return true;

        std::shared_ptr<HBITMAP> shared_bmp(&hCaptureBitmap, [&](HBITMAP* bmp) {DeleteObject(bmp);});

        auto original = SelectObject(hCaptureDC, hCaptureBitmap);
        if (original == nullptr)
            return true;

        if (!BitBlt(hCaptureDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY | CAPTUREBLT))
            return true;

        BITMAPINFO bmi = { 0 };
        bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
        bmi.bmiHeader.biWidth = width;
        bmi.bmiHeader.biHeight = height;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 32;
        bmi.bmiHeader.biCompression = BI_RGB;

        std::vector<RGBQUAD> pPixels(width * height);

        auto res = GetDIBits(
            hCaptureDC,
            hCaptureBitmap,
            0,
            height,
            pPixels.data(),
            &bmi,
            DIB_RGB_COLORS
        );

        if (res <= 0 || res == ERROR_INVALID_PARAMETER)
            return true;

        auto ret = pPixels[0].rgbRed == MAGIC;
        return ret;
    }
    catch (...)
    {
        return true;
    }
#else
    return true;
#endif
}
void
draw()
{
   if (!gIsVisible) {
      return;
   }

   ImGui::SetNextWindowSize(ImVec2(600, 300), ImGuiSetCond_FirstUseEver);

   if (!ImGui::Begin("Threads", &gIsVisible)) {
      ImGui::End();
      return;
   }

   sThreadsCache.clear();

   coreinit::internal::lockScheduler();
   auto core0Thread = coreinit::internal::getCoreRunningThread(0);
   auto core1Thread = coreinit::internal::getCoreRunningThread(1);
   auto core2Thread = coreinit::internal::getCoreRunningThread(2);
   auto firstThread = coreinit::internal::getFirstActiveThread();

   for (auto thread = firstThread; thread; thread = thread->activeLink.next) {
      ThreadInfo tinfo;
      tinfo.thread = thread;
      tinfo.id = thread->id;
      tinfo.name = thread->name ? thread->name.get() : "";
      tinfo.state = thread->state;
      tinfo.priority = thread->priority;
      tinfo.basePriority = thread->basePriority;
      tinfo.affinity = thread->attr & coreinit::OSThreadAttributes::AffinityAny;

      if (thread == core0Thread) {
         tinfo.coreId = 0;
      } else if (thread == core1Thread) {
         tinfo.coreId = 1;
      } else if (thread == core2Thread) {
         tinfo.coreId = 2;
      } else {
         tinfo.coreId = -1;
      }

      tinfo.coreTimeNs = thread->coreTimeConsumedNs;

      if (tinfo.coreId != -1) {
         tinfo.coreTimeNs += coreinit::internal::getCoreThreadRunningTime(0);
      }

      sThreadsCache.push_back(tinfo);
   }

   coreinit::internal::unlockScheduler();

   ImGui::Columns(8, "threadList", false);
   ImGui::SetColumnOffset(0, ImGui::GetWindowWidth() * 0.00f);
   ImGui::SetColumnOffset(1, ImGui::GetWindowWidth() * 0.05f);
   ImGui::SetColumnOffset(2, ImGui::GetWindowWidth() * 0.35f);
   ImGui::SetColumnOffset(3, ImGui::GetWindowWidth() * 0.50f);
   ImGui::SetColumnOffset(4, ImGui::GetWindowWidth() * 0.60f);
   ImGui::SetColumnOffset(5, ImGui::GetWindowWidth() * 0.70f);
   ImGui::SetColumnOffset(6, ImGui::GetWindowWidth() * 0.75f);
   ImGui::SetColumnOffset(7, ImGui::GetWindowWidth() * 0.84f);

   ImGui::Text("ID"); ImGui::NextColumn();
   ImGui::Text("Name"); ImGui::NextColumn();
   ImGui::Text("NIA"); ImGui::NextColumn();
   ImGui::Text("State"); ImGui::NextColumn();
   ImGui::Text("Prio"); ImGui::NextColumn();
   ImGui::Text("Aff"); ImGui::NextColumn();
   ImGui::Text("Core"); ImGui::NextColumn();
   ImGui::Text("Core Time"); ImGui::NextColumn();
   ImGui::Separator();

   for (auto &thread : sThreadsCache) {
      // ID
      if (thread.thread == getActiveThread()) {
         // Highlight the currently active thread
         // TODO: Clean this up
         auto idStr = fmt::format("{}", thread.id);
         auto drawList = ImGui::GetWindowDrawList();
         auto lineHeight = ImGui::GetTextLineHeight();
         float glyphWidth = ImGui::CalcTextSize("FF").x - ImGui::CalcTextSize("F").x;
         float idWidth = glyphWidth * idStr.length();
         auto rootPos = ImGui::GetCursorScreenPos();
         auto idMin = ImVec2(rootPos.x - 1, rootPos.y);
         auto idMax = ImVec2(rootPos.x + idWidth + 2, rootPos.y + lineHeight + 1);
         drawList->AddRectFilled(idMin, idMax, ImColor(CurrentBgColor), 2.0f);
         ImGui::TextColored(CurrentColor, "%s", idStr.c_str());
      } else {
         ImGui::Text("%d", thread.id);
      }
      ImGui::NextColumn();

      // Name
      if (isPaused()) {
         auto threadName = thread.name;

         if (thread.name.size() == 0) {
            threadName = fmt::format("(Unnamed Thread {})", thread.id);
         }

         if (ImGui::Selectable(threadName.c_str())) {
            setActiveThread(thread.thread);
         }
      } else {
         ImGui::Text("%s", thread.name.c_str());
      }

      ImGui::NextColumn();

      // NIA
      if (isPaused()) {
         ImGui::Text("%08x", getThreadNia(thread.thread));
      } else {
         ImGui::Text("        ");
      }

      ImGui::NextColumn();

      // Thread State
      ImGui::Text("%s", coreinit::enumAsString(thread.state).c_str());
      ImGui::NextColumn();

      // Priority
      ImGui::Text("%d (%d)", thread.priority, thread.basePriority);
      ImGui::NextColumn();

      // Affinity
      std::string coreAff;

      if (thread.affinity & coreinit::OSThreadAttributes::AffinityCPU0) {
         coreAff += "0";
      }

      if (thread.affinity & coreinit::OSThreadAttributes::AffinityCPU1) {
         if (coreAff.size() != 0) {
            coreAff += "|1";
         } else {
            coreAff += "1";
         }
      }

      if (thread.affinity & coreinit::OSThreadAttributes::AffinityCPU2) {
         if (coreAff.size() != 0) {
            coreAff += "|2";
         } else {
            coreAff += "2";
         }
      }

      ImGui::Text("%s", coreAff.c_str());
      ImGui::NextColumn();

      // Core Id
      if (thread.coreId != -1) {
         ImGui::Text("%d", thread.coreId);
      }

      ImGui::NextColumn();

      // Core Time
      ImGui::Text("%" PRIu64, thread.coreTimeNs / 1000);
      ImGui::NextColumn();
   }

   ImGui::Columns(1);
   ImGui::End();
}