/** * Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex * must be held, by this order. If there are still references to the * framebuffer, nothing will happen. */ static INLINE void stw_framebuffer_destroy_locked( struct stw_framebuffer *fb ) { struct stw_framebuffer **link; /* check the reference count */ fb->refcnt--; if (fb->refcnt) { pipe_mutex_unlock( fb->mutex ); return; } 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); ReleaseDC(fb->hWnd, fb->hDC); pipe_mutex_unlock( fb->mutex ); pipe_mutex_destroy( fb->mutex ); FREE( fb ); }
/** * 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 ); }