/** * Queue a composition. * * The stw_framebuffer object must have its mutex locked. The mutex will * be unlocked here before returning. */ BOOL stw_framebuffer_present_locked(HDC hdc, struct stw_framebuffer *fb, struct pipe_resource *res) { if (stw_dev->callbacks.wglCbPresentBuffers && stw_dev->stw_winsys->compose) { GLCBPRESENTBUFFERSDATA data; memset(&data, 0, sizeof data); data.magic1 = 2; data.magic2 = 0; data.AdapterLuid = stw_dev->AdapterLuid; data.rect = fb->client_rect; data.pPrivateData = (void *)res; stw_notify_current_locked(fb); stw_framebuffer_unlock(fb); return stw_dev->callbacks.wglCbPresentBuffers(hdc, &data); } else { struct pipe_screen *screen = stw_dev->screen; stw_dev->stw_winsys->present( screen, res, hdc ); stw_framebuffer_update(fb); stw_notify_current_locked(fb); stw_framebuffer_unlock(fb); return TRUE; } }
BOOL APIENTRY DrvSetPixelFormat(HDC hdc, LONG iPixelFormat) { uint count; uint index; struct stw_framebuffer *fb; if (!stw_dev) return FALSE; index = (uint) iPixelFormat - 1; count = stw_pixelformat_get_count(); if (index >= count) return FALSE; fb = stw_framebuffer_from_hdc_locked(hdc); if (fb) { /* * SetPixelFormat must be called only once. However ignore * pbuffers, for which the framebuffer object is created first. */ boolean bPbuffer = fb->bPbuffer; stw_framebuffer_unlock( fb ); return bPbuffer; } fb = stw_framebuffer_create(hdc, iPixelFormat); if (!fb) { return FALSE; } stw_framebuffer_unlock( fb ); /* Some applications mistakenly use the undocumented wglSetPixelFormat * function instead of SetPixelFormat, so we call SetPixelFormat here to * avoid opengl32.dll's wglCreateContext to fail */ if (GetPixelFormat(hdc) == 0) { BOOL bRet = SetPixelFormat(hdc, iPixelFormat, NULL); if (!bRet) { debug_printf("SetPixelFormat failed\n"); } } return TRUE; }
BOOL APIENTRY DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data) { struct stw_framebuffer *fb; struct pipe_screen *screen; struct pipe_resource *res; if (!stw_dev) return FALSE; fb = stw_framebuffer_from_hdc( hdc ); if (fb == NULL) return FALSE; screen = stw_dev->screen; res = (struct pipe_resource *)data->pPrivateData; if (data->hSharedSurface != fb->hSharedSurface) { if (fb->shared_surface) { stw_dev->stw_winsys->shared_surface_close(screen, fb->shared_surface); fb->shared_surface = NULL; } fb->hSharedSurface = data->hSharedSurface; if (data->hSharedSurface && stw_dev->stw_winsys->shared_surface_open) { fb->shared_surface = stw_dev->stw_winsys->shared_surface_open(screen, fb->hSharedSurface); } } if (!fb->minimized) { if (fb->shared_surface) { stw_dev->stw_winsys->compose(screen, res, fb->shared_surface, &fb->client_rect, data->PresentHistoryToken); } else { stw_dev->stw_winsys->present( screen, res, hdc ); } } stw_framebuffer_update(fb); stw_notify_current_locked(fb); stw_framebuffer_unlock(fb); return TRUE; }
/** * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx */ LRESULT CALLBACK stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam) { struct stw_tls_data *tls_data; PCWPSTRUCT pParams = (PCWPSTRUCT)lParam; struct stw_framebuffer *fb; tls_data = stw_tls_get_data(); if (!tls_data) return 0; if (nCode < 0 || !stw_dev) return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); /* We check that the stw_dev object is initialized before we try to do * anything with it. Otherwise, in multi-threaded programs there's a * chance of executing this code before the stw_dev object is fully * initialized. */ if (stw_dev && stw_dev->initialized) { if (pParams->message == WM_WINDOWPOSCHANGED) { /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according * to http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it * can be masked out by the application. */ LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam; if ((lpWindowPos->flags & SWP_SHOWWINDOW) || !(lpWindowPos->flags & SWP_NOMOVE) || !(lpWindowPos->flags & SWP_NOSIZE)) { fb = stw_framebuffer_from_hwnd( pParams->hwnd ); if (fb) { /* Size in WINDOWPOS includes the window frame, so get the size * of the client area via GetClientRect. */ stw_framebuffer_get_size(fb); stw_framebuffer_unlock(fb); } } } else if (pParams->message == WM_DESTROY) { stw_lock_framebuffers(stw_dev); fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd ); if (fb) stw_framebuffer_release_locked(fb); stw_unlock_framebuffers(stw_dev); } } return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); }
int stw_pixelformat_get(HDC hdc) { int iPixelFormat = 0; struct stw_framebuffer *fb; fb = stw_framebuffer_from_hdc(hdc); if (fb) { iPixelFormat = fb->iPixelFormat; stw_framebuffer_unlock(fb); } return iPixelFormat; }
/** * Decrement the reference count on the given stw_framebuffer object. * If the reference count hits zero, destroy the object. * * Note: Both stw_dev::fb_mutex and stw_framebuffer::mutex must already be * locked. After this function completes, the fb's mutex will be unlocked. */ void stw_framebuffer_release_locked(struct stw_framebuffer *fb) { struct stw_framebuffer **link; assert(fb); assert(stw_own_mutex(&fb->mutex)); assert(stw_own_mutex(&stw_dev->fb_mutex)); /* check the reference count */ fb->refcnt--; if (fb->refcnt) { stw_framebuffer_unlock(fb); return; } /* remove this stw_framebuffer from the device's linked list */ link = &stw_dev->fb_head; while (*link != fb) link = &(*link)->next; assert(*link); *link = fb->next; fb->next = NULL; if (fb->shared_surface) stw_dev->stw_winsys->shared_surface_close(stw_dev->screen, fb->shared_surface); stw_st_destroy_framebuffer_locked(fb->stfb); stw_framebuffer_unlock(fb); DeleteCriticalSection(&fb->mutex); FREE( fb ); }
BOOL APIENTRY DrvSwapBuffers(HDC hdc) { struct stw_context *ctx; struct stw_framebuffer *fb; if (!stw_dev) return FALSE; fb = stw_framebuffer_from_hdc( hdc ); if (fb == NULL) return FALSE; if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) { stw_framebuffer_unlock(fb); return TRUE; } ctx = stw_current_context(); if (ctx) { if (ctx->hud) { /* Display the HUD */ struct pipe_resource *back = stw_get_framebuffer_resource(fb->stfb, ST_ATTACHMENT_BACK_LEFT); if (back) { hud_draw(ctx->hud, back); } } if (ctx->current_framebuffer == fb) { /* flush current context */ ctx->st->flush(ctx->st, ST_FLUSH_END_OF_FRAME, NULL); } } if (stw_dev->swap_interval != 0) { wait_swap_interval(fb); } return stw_st_swap_framebuffer_locked(hdc, fb->stfb); }