static void vigs_gl_backend_wgl_destroy(struct vigs_backend *backend)
{
    struct vigs_gl_backend_wgl *gl_backend_wgl = (struct vigs_gl_backend_wgl*)backend;

    vigs_gl_backend_cleanup(&gl_backend_wgl->base);

    gl_backend_wgl->wglDeleteContext(gl_backend_wgl->ctx);
    gl_backend_wgl->wglDeleteContext(gl_backend_wgl->read_pixels_ctx);
    gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, gl_backend_wgl->sfc_dc);
    gl_backend_wgl->wglDestroyPbufferARB(gl_backend_wgl->sfc);
    gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->read_pixels_sfc, gl_backend_wgl->read_pixels_sfc_dc);
    gl_backend_wgl->wglDestroyPbufferARB(gl_backend_wgl->read_pixels_sfc);

    ReleaseDC(gl_backend_wgl->win, gl_backend_wgl->dc);
    DestroyWindow(gl_backend_wgl->win);

    FreeLibrary(gl_backend_wgl->handle);

    vigs_backend_cleanup(&gl_backend_wgl->base.base);

    g_free(gl_backend_wgl);

    UnregisterClassA((LPCTSTR)VIGS_WGL_WIN_CLASS, NULL);

    VIGS_LOG_DEBUG("destroyed");
}
Exemple #2
0
static void vigs_io_write(void *opaque, hwaddr offset,
                          uint64_t value, unsigned size)
{
    VIGSState *s = opaque;

    switch (offset) {
    case VIGS_REG_EXEC:
        vigs_server_dispatch(s->server, value);
        break;
    case VIGS_REG_CON:
        if (((s->reg_con & VIGS_REG_CON_VBLANK_ENABLE) == 0) &&
            (value & VIGS_REG_CON_VBLANK_ENABLE)) {
            VIGS_LOG_DEBUG("VBLANK On");
        } else if (((value & VIGS_REG_CON_VBLANK_ENABLE) == 0) &&
                   (s->reg_con & VIGS_REG_CON_VBLANK_ENABLE)) {
            VIGS_LOG_DEBUG("VBLANK Off");
        }

        s->reg_con = value & VIGS_REG_CON_MASK;

        vigs_update_irq(s);
        break;
    case VIGS_REG_INT:
        if (value & VIGS_REG_INT_VBLANK_PENDING) {
            value &= ~VIGS_REG_INT_VBLANK_PENDING;
        } else {
            value |= (s->reg_int & VIGS_REG_INT_VBLANK_PENDING);
        }

        if (value & VIGS_REG_INT_FENCE_ACK_PENDING) {
            value &= ~VIGS_REG_INT_FENCE_ACK_PENDING;
        } else {
            value |= (s->reg_int & VIGS_REG_INT_FENCE_ACK_PENDING);
        }

        s->reg_int = value & VIGS_REG_INT_MASK;

        vigs_update_irq(s);
        break;
    default:
        VIGS_LOG_CRITICAL("Bad register 0x%X write", (uint32_t)offset);
        break;
    }
}
Exemple #3
0
static int vigs_device_init(PCIDevice *dev)
{
    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
    struct vigs_backend *backend = NULL;

    XSetErrorHandler(x_error_handler);
    XInitThreads();

    vigs_display = XOpenDisplay(0);

    if (!vigs_display) {
        fprintf(stderr, "Cannot open X display\n");
        exit(1);
    }

    vigs_render_queue = work_queue_create("render_queue");

    vigs_log_init();

    if (s->vram_size < 16 * 1024 * 1024) {
        VIGS_LOG_WARN("\"vram_size\" is too small, defaulting to 16mb");
        s->vram_size = 16 * 1024 * 1024;
    }

    if (s->ram_size < 1 * 1024 * 1024) {
        VIGS_LOG_WARN("\"ram_size\" is too small, defaulting to 1mb");
        s->ram_size = 1 * 1024 * 1024;
    }

    pci_config_set_interrupt_pin(dev->config, 1);

    memory_region_init_ram(&s->vram_bar, OBJECT(s),
                           TYPE_VIGS_DEVICE ".vram",
                           s->vram_size);

    memory_region_init_ram(&s->ram_bar, OBJECT(s),
                           TYPE_VIGS_DEVICE ".ram",
                           s->ram_size);

    memory_region_init_io(&s->io_bar, OBJECT(s),
                          &vigs_io_ops,
                          s,
                          TYPE_VIGS_DEVICE ".io",
                          VIGS_IO_SIZE);

    pci_register_bar(&s->dev.pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->vram_bar);
    pci_register_bar(&s->dev.pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_bar);
    pci_register_bar(&s->dev.pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_bar);

    backend = vigs_gl_backend_create(vigs_display);

    if (!backend) {
        goto fail;
    }

    s->fenceman = vigs_fenceman_create();

    s->fence_ack_bh = qemu_bh_new(vigs_fence_ack_bh, s);

    s->con = graphic_console_init(DEVICE(dev), 0, &vigs_hw_ops, s);

    if (!s->con) {
        goto fail;
    }

    s->server = vigs_server_create(memory_region_get_ram_ptr(&s->vram_bar),
                                   memory_region_get_ram_ptr(&s->ram_bar),
                                   &vigs_dpy_ops,
                                   s,
                                   backend,
                                   vigs_render_queue);

    if (!s->server) {
        goto fail;
    }

    vigs_wsi = s->dev.wsi = &s->server->wsi;

    VIGS_LOG_INFO("VIGS initialized");

    VIGS_LOG_DEBUG("vram_size = %u", s->vram_size);
    VIGS_LOG_DEBUG("ram_size = %u", s->ram_size);

    return 0;

fail:
    if (backend) {
        backend->destroy(backend);
    }

    if (s->fence_ack_bh) {
        qemu_bh_delete(s->fence_ack_bh);
    }

    if (s->fenceman) {
        vigs_fenceman_destroy(s->fenceman);
    }

    memory_region_destroy(&s->io_bar);
    memory_region_destroy(&s->ram_bar);
    memory_region_destroy(&s->vram_bar);

    vigs_log_cleanup();

    return -1;
}
struct vigs_backend *vigs_gl_backend_create(void *display)
{
    WNDCLASSEXA vigs_win_class;
    HWND tmp_win = NULL;
    HDC tmp_dc = NULL;
    HGLRC tmp_ctx = NULL;
    int config_id = 0;
    PIXELFORMATDESCRIPTOR tmp_pixfmt = {
        .nSize = sizeof(PIXELFORMATDESCRIPTOR),
        .nVersion = 1,
        .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        .iPixelType = PFD_TYPE_RGBA,
        .cColorBits = 32,
        .cDepthBits = 24,
        .cStencilBits = 8,
        .iLayerType = PFD_MAIN_PLANE,
    };
    const char *ext_str = NULL;
    struct vigs_gl_backend_wgl *gl_backend_wgl = NULL;

    vigs_win_class.cbSize = sizeof(WNDCLASSEXA);
    vigs_win_class.style = 0;
    vigs_win_class.lpfnWndProc = &DefWindowProcA;
    vigs_win_class.cbClsExtra = 0;
    vigs_win_class.cbWndExtra = 0;
    vigs_win_class.hInstance = NULL;
    vigs_win_class.hIcon = NULL;
    vigs_win_class.hCursor = NULL;
    vigs_win_class.hbrBackground = NULL;
    vigs_win_class.lpszMenuName =  NULL;
    vigs_win_class.lpszClassName = VIGS_WGL_WIN_CLASS;
    vigs_win_class.hIconSm = NULL;

    if (!RegisterClassExA(&vigs_win_class)) {
        VIGS_LOG_CRITICAL("Unable to register window class");
        return NULL;
    }

    gl_backend_wgl = g_malloc0(sizeof(*gl_backend_wgl));

    vigs_backend_init(&gl_backend_wgl->base.base,
                      &gl_backend_wgl->base.ws_info.base);

    gl_backend_wgl->handle = LoadLibraryA("opengl32");

    if (!gl_backend_wgl->handle) {
        VIGS_LOG_CRITICAL("Unable to load opengl32.dll");
        goto fail;
    }

    VIGS_WGL_GET_PROC(PFNWGLCREATECONTEXTPROC, wglCreateContext, fail);
    VIGS_WGL_GET_PROC(PFNWGLDELETECONTEXTPROC, wglDeleteContext, fail);
    VIGS_WGL_GET_PROC(PFNWGLGETPROCADDRESSPROC, wglGetProcAddress, fail);
    VIGS_WGL_GET_PROC(PFNWGLMAKECURRENTPROC, wglMakeCurrent, fail);
    VIGS_WGL_GET_PROC(PFNWGLGETCURRENTCONTEXTPROC, wglGetCurrentContext, fail);
    VIGS_WGL_GET_PROC(PFNWGLSHARELISTSPROC, wglShareLists, fail);

    tmp_win = CreateWindow(VIGS_WGL_WIN_CLASS, "VIGSWin",
                           WS_DISABLED | WS_POPUP,
                           0, 0, 1, 1, NULL, NULL, 0, 0);

    if (!tmp_win) {
        VIGS_LOG_CRITICAL("Unable to create window");
        goto fail;
    }

    tmp_dc = GetDC(tmp_win);

    if (!tmp_dc) {
        VIGS_LOG_CRITICAL("Unable to get window DC");
        goto fail;
    }

    config_id = ChoosePixelFormat(tmp_dc, &tmp_pixfmt);

    if (!config_id) {
        VIGS_LOG_CRITICAL("ChoosePixelFormat failed");
        goto fail;
    }

    if (!SetPixelFormat(tmp_dc, config_id, &tmp_pixfmt)) {
        VIGS_LOG_CRITICAL("SetPixelFormat failed");
        goto fail;
    }

    tmp_ctx = gl_backend_wgl->wglCreateContext(tmp_dc);
    if (!tmp_ctx) {
        VIGS_LOG_CRITICAL("wglCreateContext failed");
        goto fail;
    }

    if (!gl_backend_wgl->wglMakeCurrent(tmp_dc, tmp_ctx)) {
        VIGS_LOG_CRITICAL("wglMakeCurrent failed");
        goto fail;
    }

    /*
     * WGL extensions couldn't be queried by glGetString(), we need to use
     * wglGetExtensionsStringARB or wglGetExtensionsStringEXT for this, which
     * themselves are extensions
     */
    gl_backend_wgl->wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
        gl_backend_wgl->wglGetProcAddress((LPCSTR)"wglGetExtensionsStringARB");
    gl_backend_wgl->wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
        gl_backend_wgl->wglGetProcAddress((LPCSTR)"wglGetExtensionsStringEXT");

    if (gl_backend_wgl->wglGetExtensionsStringARB) {
        ext_str = gl_backend_wgl->wglGetExtensionsStringARB(tmp_dc);
    } else if (gl_backend_wgl->wglGetExtensionsStringEXT) {
        ext_str = gl_backend_wgl->wglGetExtensionsStringEXT();
    }

    if (!ext_str) {
        VIGS_LOG_CRITICAL("Unable to obtain WGL extension string");
        goto fail;
    }

    VIGS_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, PFNWGLCREATEPBUFFERARBPROC, wglCreatePbufferARB);
    VIGS_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, PFNWGLGETPBUFFERDCARBPROC, wglGetPbufferDCARB);
    VIGS_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB);
    VIGS_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB);
    VIGS_WGL_GET_EXT_PROC(WGL_ARB_pixel_format, PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB);
    VIGS_WGL_GET_EXT_PROC(WGL_ARB_create_context, PFNWGLCREATECONTEXTATTRIBSARBPROC, wglCreateContextAttribsARB);

    VIGS_GL_GET_PROC(GenTextures, glGenTextures);
    VIGS_GL_GET_PROC(DeleteTextures, glDeleteTextures);
    VIGS_GL_GET_PROC(BindTexture, glBindTexture);
    VIGS_GL_GET_PROC(CullFace, glCullFace);
    VIGS_GL_GET_PROC(TexParameterf, glTexParameterf);
    VIGS_GL_GET_PROC(TexParameterfv, glTexParameterfv);
    VIGS_GL_GET_PROC(TexParameteri, glTexParameteri);
    VIGS_GL_GET_PROC(TexParameteriv, glTexParameteriv);
    VIGS_GL_GET_PROC(TexImage2D, glTexImage2D);
    VIGS_GL_GET_PROC(TexSubImage2D, glTexSubImage2D);
    VIGS_GL_GET_PROC(Clear, glClear);
    VIGS_GL_GET_PROC(ClearColor, glClearColor);
    VIGS_GL_GET_PROC(Disable, glDisable);
    VIGS_GL_GET_PROC(Enable, glEnable);
    VIGS_GL_GET_PROC(Finish, glFinish);
    VIGS_GL_GET_PROC(Flush, glFlush);
    VIGS_GL_GET_PROC(PixelStorei, glPixelStorei);
    VIGS_GL_GET_PROC(ReadPixels, glReadPixels);
    VIGS_GL_GET_PROC(Viewport, glViewport);
    VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
    VIGS_GL_GET_PROC(GetString, glGetString);
    VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
    VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
    VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
    VIGS_GL_GET_PROC(BindBuffer, glBindBuffer);
    VIGS_GL_GET_PROC(BufferData, glBufferData);
    VIGS_GL_GET_PROC(BufferSubData, glBufferSubData);
    VIGS_GL_GET_PROC(MapBuffer, glMapBuffer);
    VIGS_GL_GET_PROC(UnmapBuffer, glUnmapBuffer);
    VIGS_GL_GET_PROC(CreateProgram, glCreateProgram);
    VIGS_GL_GET_PROC(CreateShader, glCreateShader);
    VIGS_GL_GET_PROC(CompileShader, glCompileShader);
    VIGS_GL_GET_PROC(AttachShader, glAttachShader);
    VIGS_GL_GET_PROC(LinkProgram, glLinkProgram);
    VIGS_GL_GET_PROC(GetProgramiv, glGetProgramiv);
    VIGS_GL_GET_PROC(GetProgramInfoLog, glGetProgramInfoLog);
    VIGS_GL_GET_PROC(GetShaderiv, glGetShaderiv);
    VIGS_GL_GET_PROC(GetShaderInfoLog, glGetShaderInfoLog);
    VIGS_GL_GET_PROC(DetachShader, glDetachShader);
    VIGS_GL_GET_PROC(DeleteProgram, glDeleteProgram);
    VIGS_GL_GET_PROC(DeleteShader, glDeleteShader);
    VIGS_GL_GET_PROC(DisableVertexAttribArray, glDisableVertexAttribArray);
    VIGS_GL_GET_PROC(EnableVertexAttribArray, glEnableVertexAttribArray);
    VIGS_GL_GET_PROC(ShaderSource, glShaderSource);
    VIGS_GL_GET_PROC(UseProgram, glUseProgram);
    VIGS_GL_GET_PROC(GetAttribLocation, glGetAttribLocation);
    VIGS_GL_GET_PROC(GetUniformLocation, glGetUniformLocation);
    VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer);
    VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv);
    VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
    VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);

    VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);

    if (!vigs_gl_backend_wgl_check_gl_version(gl_backend_wgl,
                                              &gl_backend_wgl->base.is_gl_2)) {
        goto fail;
    }

    if (gl_backend_wgl->base.is_gl_2) {
        VIGS_GL_GET_PROC(GenFramebuffers, glGenFramebuffersEXT);
        VIGS_GL_GET_PROC(GenRenderbuffers, glGenRenderbuffersEXT);
        VIGS_GL_GET_PROC(DeleteFramebuffers, glDeleteFramebuffersEXT);
        VIGS_GL_GET_PROC(DeleteRenderbuffers, glDeleteRenderbuffersEXT);
        VIGS_GL_GET_PROC(BindFramebuffer, glBindFramebufferEXT);
        VIGS_GL_GET_PROC(BindRenderbuffer, glBindRenderbufferEXT);
        VIGS_GL_GET_PROC(RenderbufferStorage, glRenderbufferStorageEXT);
        VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbufferEXT);
        VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2DEXT);
    } else {
        VIGS_GL_GET_PROC(GenFramebuffers, glGenFramebuffers);
        VIGS_GL_GET_PROC(GenRenderbuffers, glGenRenderbuffers);
        VIGS_GL_GET_PROC(DeleteFramebuffers, glDeleteFramebuffers);
        VIGS_GL_GET_PROC(DeleteRenderbuffers, glDeleteRenderbuffers);
        VIGS_GL_GET_PROC(BindFramebuffer, glBindFramebuffer);
        VIGS_GL_GET_PROC(BindRenderbuffer, glBindRenderbuffer);
        VIGS_GL_GET_PROC(RenderbufferStorage, glRenderbufferStorage);
        VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbuffer);
        VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2D);
        VIGS_GL_GET_PROC(GenVertexArrays, glGenVertexArrays);
        VIGS_GL_GET_PROC(BindVertexArray, glBindVertexArray);
        VIGS_GL_GET_PROC(DeleteVertexArrays, glDeleteVertexArrays);
    }

    gl_backend_wgl->wglMakeCurrent(NULL, NULL);
    gl_backend_wgl->wglDeleteContext(tmp_ctx);
    tmp_ctx = NULL;
    ReleaseDC(tmp_win, tmp_dc);
    tmp_dc = NULL;
    DestroyWindow(tmp_win);
    tmp_win = NULL;

    gl_backend_wgl->win = CreateWindow(VIGS_WGL_WIN_CLASS, "VIGSWin",
                                       WS_DISABLED | WS_POPUP,
                                       0, 0, 1, 1, NULL, NULL, 0, 0);

    if (!gl_backend_wgl->win) {
        VIGS_LOG_CRITICAL("Unable to create window");
        goto fail;
    }

    gl_backend_wgl->dc = GetDC(gl_backend_wgl->win);

    if (!gl_backend_wgl->dc) {
        VIGS_LOG_CRITICAL("Unable to get window DC");
        goto fail;
    }

    config_id = vigs_gl_backend_wgl_choose_config(gl_backend_wgl);

    if (!config_id) {
        goto fail;
    }

    if (!vigs_gl_backend_wgl_create_surface(gl_backend_wgl, config_id,
                                            &gl_backend_wgl->sfc,
                                            &gl_backend_wgl->sfc_dc)) {
        goto fail;
    }

    if (!vigs_gl_backend_wgl_create_surface(gl_backend_wgl, config_id,
                                            &gl_backend_wgl->read_pixels_sfc,
                                            &gl_backend_wgl->read_pixels_sfc_dc)) {
        goto fail;
    }

    if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl,
                                            NULL,
                                            &gl_backend_wgl->ctx)) {
        goto fail;
    }

    if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl,
                                            gl_backend_wgl->ctx,
                                            &gl_backend_wgl->read_pixels_ctx)) {
        goto fail;
    }

    gl_backend_wgl->base.base.destroy = &vigs_gl_backend_wgl_destroy;
    gl_backend_wgl->base.has_current = &vigs_gl_backend_wgl_has_current;
    gl_backend_wgl->base.make_current = &vigs_gl_backend_wgl_make_current;
    gl_backend_wgl->base.read_pixels_make_current = &vigs_gl_backend_wgl_read_pixels_make_current;
    gl_backend_wgl->base.ws_info.context = gl_backend_wgl->ctx;

    if (!vigs_gl_backend_init(&gl_backend_wgl->base)) {
        goto fail;
    }

    VIGS_LOG_DEBUG("created");

    return &gl_backend_wgl->base.base;

fail:
    if (gl_backend_wgl->ctx) {
        gl_backend_wgl->wglDeleteContext(gl_backend_wgl->ctx);
    }
    if (gl_backend_wgl->read_pixels_ctx) {
        gl_backend_wgl->wglDeleteContext(gl_backend_wgl->read_pixels_ctx);
    }
    if (gl_backend_wgl->sfc_dc) {
        gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, gl_backend_wgl->sfc_dc);
    }
    if (gl_backend_wgl->sfc) {
        gl_backend_wgl->wglDestroyPbufferARB(gl_backend_wgl->sfc);
    }
    if (gl_backend_wgl->read_pixels_sfc_dc) {
        gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->read_pixels_sfc, gl_backend_wgl->read_pixels_sfc_dc);
    }
    if (gl_backend_wgl->read_pixels_sfc) {
        gl_backend_wgl->wglDestroyPbufferARB(gl_backend_wgl->read_pixels_sfc);
    }
    if (gl_backend_wgl->dc) {
        ReleaseDC(gl_backend_wgl->win, gl_backend_wgl->dc);
    }
    if (gl_backend_wgl->win) {
        DestroyWindow(gl_backend_wgl->win);
    }
    if (gl_backend_wgl->wglMakeCurrent && tmp_ctx) {
        gl_backend_wgl->wglMakeCurrent(NULL, NULL);
    }
    if (gl_backend_wgl->wglDeleteContext && tmp_ctx) {
        gl_backend_wgl->wglDeleteContext(tmp_ctx);
    }
    if (tmp_dc) {
        ReleaseDC(tmp_win, tmp_dc);
    }
    if (tmp_win) {
        DestroyWindow(tmp_win);
    }
    if (gl_backend_wgl->handle) {
        FreeLibrary(gl_backend_wgl->handle);
    }

    vigs_backend_cleanup(&gl_backend_wgl->base.base);

    g_free(gl_backend_wgl);

    UnregisterClassA((LPCTSTR)VIGS_WGL_WIN_CLASS, NULL);

    return NULL;
}