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"); }
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; } }
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; }